有人能解释一下特殊的std::函数模板参数列表语法(这个奇怪的类型(Types..))吗

Can someone explain the special std::function template parameter list syntax(this strange Type(Types...))?

本文关键字:列表 语法 类型 参数 Types std 能解释 一下 函数模板      更新时间:2023-10-16

有人能解释一下特殊的std::function语法(这个奇怪的Type(Types...))吗?这些括号是什么?我知道里面的意思是函数的参数列表。

我只是想知道这个语法是什么意思。

//What am I doing? Can someone explain?
std::vector<int>      a; // 
std::vector<int(int)> b; // it counts as a type
//or
std::tuple<double, double> t1{0.0, 0.0}; // okey
std::tuple<double(double)> t2{0.0, 0.0}; // not okey, not the same as above(please explain what happens)

Type(Types...)不是"特殊语法"。std::functionR(Args...)的原因是它专门用于函数类型R(Args...)。以下是标准的声明:

template<class> class function; // undefined
template<class R, class... ArgTypes> class function<R(ArgTypes...)>;

需要理解的重要一点是R(ArgTypes...)语法指定了一个函数类型。如果声明一个函数,例如int foo(int arg),则foo的类型为int(int)

你可以创建自己的结构来接受这样的论点:

template <class>
struct X;
template <class R, class ...Args>
struct X<R(Args...)> {
typedef R result_type;
// ... whatever
};

不能将int(int)std::vectorstd::tuple一起使用的原因是它们的声明:

template<class T, class Allocator = allocator<T>> class vector;
template<class... Types> class tuple;

当您执行std::vector<int(int)>时,您将T替换为int(int),这将不起作用,因为std::allocator<int(int)>的构造将失败(您无法分配函数类型)。

当您执行std::tuple<int(int)>时,您将传递int(int)作为参数包Types中的第一个类型,这也不起作用,因为您不能将函数类型作为数据成员。

不能将函数类型作为std::vector(或std::tuple)的模板参数,但可以在此角色中使用函数指针类型。例如,

int foo(int x) { return 2 * x; }
int bar(int x) { return 3 * x; }
std::vector<int(*)(int)> v{&foo, &bar}; // & is optional here
std::cout << v[0](5); // Calls foo(5), outputs 10
std::cout << v[1](5); // Calls bar(5), outputs 15

当您在C++中声明一个函数时,您实际上使用了完全相同的语法

return_type function_name(parameter_type1, parameter_type2 /* and so on */)

我希望你不要觉得奇怪。在函数声明中,语法括号环绕着参数列表。

现在,如果从该语法中删除function_name,则只剩下函数类型本身,即从声明中"提取"的

return_type (parameter_type1, parameter_type2)

这就是在C++中描述普通函数类型的方法。事实上,它是直接从C那里继承来的。没有什么新的、奇怪的或不寻常的。

例如,当您声明时

int a[10];

您实际上是在将名称a声明为具有类型int [10]。以同样的方式,当您声明时

double a(double);

您实际上是在将名称a声明为具有类型double (double)

并且不能将函数类型用作容器元素类型或元组元素类型。函数类型不是对象类型。这些上下文实际上需要对象类型。

但是您可以(而且必须)将它用作std::function的模板参数。