Question

I'm having difficulty packaging std::stoll into a std::function. The naive

std::function<std::int64_t(std::string const&)> obj = std::stoll;

fails because std::stoll is an overload of two functions (something cppreference doesn't mention [at the time of asking]), one taking std::string the other std::wstring as first argument. So how am I getting what I want?

I know that I could instead use a lambda that calls std::stoll, but I'm looking for a solution of the form

auto parser = ???
std::function<std::int64_t(std::string const&)> obj{parser};
Was it helpful?

Solution

You can cast an overloaded function pointer to disambiguate it:

function<int64_t(string const&)> obj =
  static_cast<int64_t(*)(string const&)>(stoll);

Edit: you also need to bind the default arguments, since stoll is a three-argument function and you are trying to make it take just one argument:

function<int64_t(string const&)> obj =
  std::bind(static_cast<int64_t(*)(string const&, size_t*, int)>(stoll),
    placeholders::_1, nullptr, 10);

OTHER TIPS

Wrap it in a functor:

struct StringToLongLong {
    long long operator () (const std::string& s) const { return stoll(s); }
    long long operator () (const std::wstring& s) const { return stoll(s); }
};
std::function<std::int64_t(std::string const&)> obj = StringToLongLong();

Note: The functor might be locally defined in a function.

If the functor is no (!) local class in a function (See @MSalters comment):

struct StringToLongLong {
    template <typename String>
    long long operator () (const String& s) const { return stoll(s); }
};
std::function<std::int64_t(std::string const&)> obj = StringToLongLong();

Note: Member templates are invalid if the functor is locally defined in a function.

This looks like a problem for overload sets. Written in C++1y as it saves a decltype

#define OVERLOAD_SET(F) struct {\
  template<typename...Args> auto operator()(Args&&...args)const{\
    return (F)(std::forward<Args>(args)...);\
  }\
}

now we can

static OVERLOAD_SET(std::stoll) os_stroll;

and os_stroll can be passed to std::function and it just does the right thing.

You can even enable ADL if you like:

#define ADL_OVERLOAD_SET(NS, F) struct {\
  template<typename...Args> auto operator()(Args&&...args)const{\
    using NS::F;
    return F(std::forward<Args>(args)...);\
  }\
}

Another optional improvement:

  /* cast to function pointer.  Copy paste for each calling convention */\
  template<typename R, typename Args...>\
  operator R(*)(Args...)() const {\
    return [](Args...args){return (F)(std::forward<Args>(args)...);};\
  }\

or be a bit more strict about what Args... to accept (the above will return a function pointer iff the types convert. It should also probably do SFINAE to generate earlier failure).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top