如何将重载函数作为模板化函数参数传递

How do I pass an overloaded function as a templated function parameter?

本文关键字:函数 参数传递 重载      更新时间:2023-10-16

所以我要做的是写一个泛型函数,它接受一个字符串,将它分割成一个类型的向量。这是我的代码,问题是它无法将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;
}

只是关于你的代码的几点。

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

可能使用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;
}