以下模板在C ++中的作用是什么?
template <class R, class T>
struct my_type<R(*)(T)> { typedef T type; };
具体来说,*在这种背景下代表什么?
答案 0 :(得分:3)
在此上下文中,它使模板特化引用一个指向函数的指针,该函数被声明为接受类型T
的单个参数,并返回类型R
的值。专门化提取参数类型并使其可用作typedef。
示例(demo):
#include <iostream>
#include <type_traits>
int foo(float);
template <typename T>
struct my_type;
template <class R, class T>
struct my_type<R(*)(T)> { typedef T type; };
int main() {
std::cout
<< std::is_same<
float,
typename my_type<decltype(&foo)>::type
>::value
<< "\n";
return 0;
}
这会输出1
因为float
和typename my_type<decltype(&foo)>::type
都指向相同的类型 - decltype(&foo)
是类型int (*)(float)
,它与特化R(*)(T)
匹配1}}。
答案 1 :(得分:0)
cdhowie上面给出了很好的答案,但我觉得它更能解释什么是模板专业化,而不是解释具体问题: *
代表R(*)(T)
{ EM>
为此,我们需要看看我们如何在C ++的类型系统中指定类型。如果你已经了解了大部分或全部内容,请不要被冒犯,但我认为如果我从基础开始,我可以最好地解释它。如果不是你,也许其他人可以从中学习(我自己很困惑C(++)的类型系统,来自Pascal :))。如果你只想要答案,那就是这篇文章的最后一句话。
假设我们要声明一个名为foo
的变量int
。
int foo;
嗯,这很容易。现在,让我们将其更改为3个整数的数组:
int foo[3];
重要的是要意识到我们在这里所做的一切。您可能会认为数组说明符只是最后一个,但事实并非如此。因为,为了声明某个数组,我们需要在命名变量的标识符之后添加括号,或者在这种情况下添加foo
。当您想要将此声明扩展为2×int[3]
:
int foo[2][3];
因此,通过在foo
声明中用foo[2]
替换int foo[3]
,我们得到int foo[2][3]
。这就是foo
是一个2×[3×int
] 数组的数组的原因。当我们添加括号(我们实际上允许这样做)时,这变得更加明显:
int foo; // [int]
int (foo[3]); // array of 3×[int]
int ((foo[2])[3]); // array of 2×[array of 3×[int]]
C ++使用类似的指针系统。要声明指向某个内容的指针,使用*
为标识符添加前缀。
int foo; // [int]
int (*foo); // pointer to [int] (same as: int *foo)
int (*(*foo)); // pointer to [pointer to [int]] (same as: int **foo)
因此,我们已在每一行上用foo
替换(*foo)
。
这是事情变得有趣的地方。我们需要为标识符添加*
作为指针的前缀,并使用[]
为数组后缀,但是,int *foo[3]
是什么意思?事实证明,int *foo[3]
被解析为int *(foo[3])
。所以,它是一个3×[指向int
] 的指针的数组。要获得指向[3×int
] 数组的指针,我们需要执行:int (*foo)[3]
int *(foo[3]); // array of 3×[pointer to [int]] (same as: int *foo[3])
int (*foo)[3]; // pointer to [array of 3×[int]]
现在,要回答您的问题,我们需要查看函数声明。这实际上类似于数组。要声明一个函数,请在标识符后面添加括号和参数列表:
int foo; // [int]
int (foo()); // function returning [int] (same as: int foo())
现在我们也可以应用以上规则:
int foo; // [int]
int (foo()); // function returning [int] (same as: int foo())
int ((*foo)()); // pointer to [function returning [int]] (same as: int (*foo)())
int ((*(foo[2]))()); // array of 2×[pointer to [function returning [int]]] (same as: int (*foo[2])())
要命名没有标识符的类型,只需删除标识符即可。因此,上面示例中第三个foo
的类型只是int(*)()
。请注意,这里的括号是强制性的。如果它是int*()
,那么它将是函数返回[指向[int]] 的指针。
提示:要弄清楚某事物的类型,请使用自下而上的方法,从标识符(或标识符所在的位置)开始,向外工作,使用以下注释:{{ 1}代表“指向...的指针”,
*
表示“数组...”,[]
代表“函数接收(x)并返回...”。根据经验:如果没有括号,右侧会在左侧之前。
现在我们可以回答你的问题:(x)
中的*
代表:一个指向函数的指针,该函数以T为参数并返回R。