我遇到了以下代码:
char (&f(...))[2];
我检查了它的类型(使用typeid和c ++ filt)并得到了:
char (&(...)) [2]
但我无法理解这种类型。 [2]是让我失望的部分。没有它,我可以在函数定义中复制类型,例如:
char (&f(...))
f与h in的类型相同(至少从typeid + c ++ filt的输出开始):
char& h(...)
答案 0 :(得分:3)
这是一个函数声明,它具有不同数量的参数,并返回对两个元素的字符数组的引用。
使用typedef可以宣布它更简单。例如
typedef char char_array[2];
char_array & f( ... );
答案 1 :(得分:2)
您可以使用cdecl并将任意类型替换为椭圆,例如int
:
char (&f(int)) [2]
导致
将
f
声明为函数(int
),返回对char
的数组2的引用[...]
替换回来,然后用语言表达你的声明。
答案 2 :(得分:2)
char (&f(...))[2];
这是函数的声明,返回对两个字符数组的引用。为了在语法上正确,需要括号。否则,&
将绑定到char
,并且由于[2]
无意义,会出现语法错误。
语法可以使用类型别名进行分解。例如:
using array_ref = char (&)[2];
array_ref f(...);
返回对数组而不是实际数组的引用的原因是因为无法从函数返回数组。这是不可能的。您只能返回引用或指向数组的指针,就像函数一样。
在所有示例中,...
都是C variadic argument pack。
我见过这种语法的唯一地方就是它被用作SFINAE的函数重载解析的一部分。通常,此函数伴随着使用模板替换来检查给定类型的属性的同名重载。如果发生替换失败,则选择第二个重载(采用可变参数包的重载)作为回退。它的回报类型是成功或失败的区别。
例如,这里的trait类检查类型是否具有成员函数f()
:
template <typename T>
struct has_f
{
private:
using true_type = char (&)[1];
using false_type = char (&)[2];
template <typename U>
static decltype(std::declval<U>().f(), true_type()) f(int);
template <typename>
static false_type f(...);
public:
static constexpr bool value = sizeof(check<T>(0)) == 1;
};
如您所见,如果T
有成员函数f()
,则返回类型的大小为1
,否则为2
。 true_type
和false_type
在很大程度上被标准特征类std::true_type
和std::false_type
取代,但这只是一个例子来说明它的用法。