有人可以解释特殊的std :: function模板参数列表语法(这种奇怪的Type(Types ...))吗?

时间:2019-01-23 21:55:49

标签: c++ templates

有人可以解释特殊的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)

3 个答案:

答案 0 :(得分:2)

Type(Types...) 不是是“特殊语法”。 std::function使用R(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中的第一种类型,这将不起作用,因为您不能让函数类型成为数据成员

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

在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)

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

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