将重载函数(如std :: stoll)打包到std :: function中

时间:2014-04-29 14:00:25

标签: c++ c++11 overloading std-function

我无法将std::stoll打包成std::function。天真的

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

失败,因为std::stoll是两个函数的重载(cppreference没有提及 [在询问时] ),其中一个是std::string另一个std::wstring作为第一个参数。那我怎么得到我想要的东西呢?

我知道我可以使用一个调用std::stoll的lambda,但我正在寻找表单的解决方案

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

3 个答案:

答案 0 :(得分:6)

您可以强制转换函数指针以消除歧义:

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

编辑:你还需要绑定默认参数,因为stoll是一个三参数函数,你试图让它只需要一个参数:

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

答案 1 :(得分:4)

用仿函数包裹它:

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();

注意:函数可以在函数中本地定义。

如果函数在函数中没有(!)本地类(参见@MSalters评论):

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();

注意:如果函数在函数中本地定义,则成员模板无效。

答案 2 :(得分:0)

这看起来像是重载集的问题。用C ++ 1y编写,因为它保存了decltype

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

现在我们可以

static OVERLOAD_SET(std::stoll) os_stroll;

os_stroll可以传递给std::function,它只做正确的事。

如果您愿意,甚至可以启用ADL:

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

另一项可选改进:

  /* 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)...);};\
  }\

或者对Args...接受的内容有点严格(如果类型转换,上面将返回一个函数指针。它也可能会执行SFINAE以生成更早的失败)。