【问题标题】:How do I pass an overloaded function as a templated function parameter? [duplicate]如何将重载函数作为模板函数参数传递? [复制]
【发布时间】:2016-09-10 21:14:29
【问题描述】:

所以我要做的是编写一个通用函数,它接受一个字符串 a 将其拆分为一个类型化向量。这是我的代码,问题是它无法将 stod 函数类型解析为我指定的通用函数包装器。

#include <string>
#include <sstream>
#include <vector>
#include <iostream>
#include <functional>

using std::vector;
using std::string;
using std::function;
using std::stringstream;


int main(int argc, const char * argv[]) {
    SplitStringToTypedVector("1.23 3.45 5.21", ' ', static_cast<double (*)(const string&, size_t*)>(&std::stod)); 

    system("pause");
    return 0;
}

template <typename T>
vector<T> SplitStringToTypedVector(const string &s, char delim, function<T (*)(const string&, size_t*)> conversionFunc) {
    vector<T> elements;
    stringstream stream;
    string element;
    while (getline(stream, element, delim)) {
        elements.push_back(conversionFunc(element));
    }
    return elements;
}

【问题讨论】:

    标签: c++ templates c++11


    【解决方案1】:

    关于您的代码的几点说明。

    (1) 在定义之前,您在 main() 中调用 SplitStringToTypedVector()。那很糟。您应该切换main()SplitStringToTypedVector() 或在main() 之前添加SplitStringToTypedVector() 的原型

    (2) 使用std::function 你必须避免(*);所以

    function<T(const string&, size_t*)> conversionFunc
    

    而不是

    function<T(*)(const string&, size_t*)> conversionFunc
    

    (3) 你的函数 conversionFunc() 被声明为接收 2 个参数。我知道std::tod 的第二个参数有一个默认值,但我不认为SplitStringToTypedVector() 能够知道它。所以用参数调用conversionFunc() 是错误的

    elements.push_back(conversionFunc(element));
    

    你必须用两个来调用它

    elements.push_back(conversionFunc(element));
    

    (4) 我不知道如何强制识别类型T 调用SplitStringToTypedVector()(我想是我的极限);但你可以明确它

    SplitStringToTypedVector<double>("1.23 3.45 5.21", ' ', static_cast<double (*)(const string&, size_t*)>(&std::stod));
    

    【讨论】:

      【解决方案2】:

      使用 lambda 解析函数类型可能更简洁,而不是担心消除 stod 的重载的歧义:

      #include <string>
      #include <sstream>
      #include <vector>
      #include <iostream>
      #include <functional>
      
      using std::vector;
      using std::string;
      using std::function;
      using std::stringstream;
      
      template <class Func>
      auto SplitStringToTypedVector(const string &s, 
                                         char delim, 
                                         Func&& conversionFunc) {
        using result_type = decltype(conversionFunc(s));
          vector<result_type> elements;
          stringstream stream;
          string element;
          while (getline(stream, element, delim)) {
              elements.push_back(conversionFunc(element));
          }
          return elements;
      }
      
      int main(int argc, const char * argv[]) {
          SplitStringToTypedVector("1.23 3.45 5.21", 
                                   ' ', 
                                   [](std::string const& s) { return std::stod(s); }); 
      
          system("pause");
          return 0;
      }
      

      【讨论】:

      • 问题标记为C++11auto 没有尾随类型的返回类型使用C++14 进入游戏。所以这个答案不适用于这个问题。至少,提一下。
      • 还有人用c++11吗?它可以用 std::result_of 修复。
      • 你知道,答案是肯定的:不幸的是,还有人仍在使用 C++98。 :-(
      • 历史告诉我们,固守过去是一种失败的策略。我强烈认为编译器应该默认使用最新的标准。
      • 这是否意味着您想将此答案放在有关 的问题上?毕竟,有人使用那种讨厌的语言吗?请教我这句话的意思。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      • 2014-08-02
      相关资源
      最近更新 更多