在回答一个问题时,我遇到了这样的代码:
template<class T, class... Ts> void foo();
template <class T, class T::value_type>
void foo() { }
它以专用于foo
模板函数的代码的形式出现,这是不对的,但这不是我的问题。我想知道为什么编译器允许这样的构造:class T::value_type
在template参数中。我的意思是,这很明显是错误的,我无法提出范围运算符可能是参数名称(模板或函数)一部分的任何情况。因此,我有两个问题:
答案 0 :(得分:5)
如评论中所述,它是elaborated type specifier。最好用一个例子来解释:
int main() {
struct foo {}; // ok
int foo = 0; // ok
int test = foo; // ok, refers to variable 'foo'
foo a; // error, 'foo' refers to variable
struct foo b; // ok, 'struct' means that name lookup searches for classes only
}
从本质上讲,您可以将它们(struct/class
,enum
)视为限制更严格的typename
,因为它们分别只允许类或枚举。另请注意,您的原始示例中允许使用typename
!
template<class T, class... Ts> void foo();
template <class T, typename T::value_type> // Ok, value_type needs to be a type
// ^^^^^^^^^^^^^^^^^^^^^^^ it's a non-type template parameter
void foo() { }
当类型和变量具有相同的名称时,或者在您具有从属名称时(例如,在class T::value_type
中,value_type
是类,之前没有class
的话,它应该是一个值。通常使用typename
。)
我无法想到范围运算符可能是参数名称的一部分的任何情况
您在这里只想到类型模板参数;非类型模板参数可以很好地使用范围运算符来命名类型。