所以我有这段代码:
#include "type_traits"
struct A{
int member;
};
struct B{
typedef A object;
typedef int member;
};
typedef std::integral_constant<B::member, B::object::*, &A::member> type;
但如果我将最后一行更改为:
typedef std::integral_constant<typename B::member, typename B::object::*, &A::member> type;
程序无法编译....
为什么添加typename
说明符导致程序无法编译?这对我来说尤其令人惊讶,因为在这种情况下我认为我需要它。
注意: 使用gcc 5.1.0
答案 0 :(得分:3)
您无法在指定类型的任何位置添加typename
。您只能,并且在使用从属类型名称时需要添加typename
。
依赖名称是这样的:
template<typename T>
void foo() { (void)T::member(); }
T::member
是一个类型,还是一个名为member
的成员函数?默认情况下,编译器会假定它不是类型。如果是类型,则必须指定typename
以消除歧义。
template<typename T>
void foo() { (void)typename T::member(); }
现在告诉编译器假设T::member
确实是一种类型。
但是,只有在T::member
的性质无法知晓的情况下,C ++语法才允许使用它。因此,在处理知识类型(如代码)时,编译器已经知道这些成员是类型。没有什么可以消除歧义。
如果您要通过模板别名更改typedef,则在编写时需要typename
:
template<typename C, typename D> // v----- Type of pointer to member?
using type = std::integral_constant<typename D::member D::object::*, &C::member>;
// Here, D::object::* don't need typename, ----^
// since only types are allowed here