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

packaging an overloaded function (like std::stoll) into std::function

本文关键字:std 函数 重载 stoll      更新时间:2023-10-16

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

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

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

将其封装在函子中:

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

注意:函子可能是在函数中局部定义的。

如果函数中的函子不是(!(局部类(请参见@MSchangers注释(:

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

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

这看起来像是重载集的问题。在保存decltype 时用C++1y编写

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

并且CCD_ 9可以被传递给CCD_。

如果你喜欢,你甚至可以启用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以生成早期的失败(。