【发布时间】:2019-10-31 06:46:32
【问题描述】:
函数模板std::transform() 采用一个范围,使用运算符对它进行逐个操作,并将结果保存在另一个范围中。在下面的示例中,该函数采用名为nl 的通用std::initializer_list 并使用(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
【问题讨论】:
-
请注意,您不能在 C++20 及更高版本的标准库中获取函数的地址:en.cppreference.com/w/cpp/language/…。此代码将具有未指定的行为或可能无法编译。相反,你应该写
[](int i) { return std::to_string(i); };,这很糟糕,但有人建议让它变得更好。 -
std::to_string有很多重载,所以std::to_string单独并不能唯一标识一个函数。见stackoverflow.com/questions/2942426/…。 -
因为函子可以是带有
operator()的任何对象,并且它无法知道它应该使用哪个模板实例化或重载。 -
函数
to_string有重载,通过将其转换为函数指针,您可以告诉编译器选择哪一个。 (见godbolt.org/z/nQrzWc,注释掉goo::foo的重载)
标签: c++ c++11 casting std function-pointers