功能模板std::transform()
包含一个范围,并用运算符对其进行逐个操作,然后将结果保存在另一个范围中。在下面的示例中,该函数采用名为std::initializer_list
的通用nl
并使用(std::string (*)(T)) std::to_string
在其上进行操作,以将其所有条目转换为字符串,然后将结果存储在一个称为字符串的数组中buffer
。
class num_list
{
public:
template<typename T>
num_list(std::initializer_list<T> nl):
size{nl.size()},
buffer(new std::string[size])
{
std::transform(nl.begin(), nl.end(), // input sequence
buffer, // output result
(std::string (*)(T))std::to_string); // unary operator
}
//...
private:
std::size_t size;
std::string * buffer;
};
我想知道为什么我们需要将std::to_string
转换成函数指针才能起作用。如果将强制类型转换为指针指向函数类型(std::string (*)(T))
,为什么代码无法使用C ++ 11编译?我无法破译编译器引发的抱怨。
error: no instance of overloaded function "std::transform" matches the argument list
答案 0 :(得分:5)
std::transform
是一个功能模板,它通过模板参数类型获取功能对象。由于类型是模板参数,因此必须推导它。 std::to_string
是重载函数,因此当您尝试推导其类型时,会得到多个结果。由于推论中没有其他内容可以帮助缩小类型,因此编译器将无法推导std::to_string
的类型,您会得到一个错误。
当您将std::to_string
转换为std::string (*)(T)
时,现在只有一个类型可以让编译器推断出该类型,并且可以成功编译。
您可以使用通用lambda代替强制转换,而不是像
那样转发至std::to_string
std::transform(nl.begin(), nl.end(), // input sequence
buffer, // output result
([](auto&& val){ return std::to_string(val);});
,但这至少需要C ++ 14。对于C ++ 11,您可以使用T
作为参数类型,例如
std::transform(nl.begin(), nl.end(), // input sequence
buffer, // output result
([](const T& val){ return std::to_string(val);});