【问题标题】:packaging an overloaded function (like std::stoll) into std::function将重载函数(如 std::stoll)打包成 std​​::function
【发布时间】:2014-04-29 14:00:25
【问题描述】:

我很难将 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};

【问题讨论】:

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


【解决方案1】:

您可以强制转换一个重载的函数指针来消除歧义:

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

【讨论】:

  • 抱歉,我收到了 error: address of overloaded function 'stoll' cannot be static_cast to type 'std::int64_t (*)(const std::string &amp;, size_t *, int)' 的叮当声。
  • 啊,是的,我错过了。我用可编译的代码编辑了我的答案。 :)
【解决方案2】:

将其包装在函子中:

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

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

【讨论】:

  • 如果 C++17 添加了 Unicode 重载,你的结构是不完整的。为什么不template&lt;typename STR&gt; long long operator() (STR const&amp; s) const() { return std::stoll(s); }
  • @MSalters 不错的建议!
【解决方案3】:

这看起来像是重载集的问题。用 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 以产生更早的失败)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    • 2015-08-04
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多