我一直在阅读有关删除类型为here的引用的信息。
它给出了以下示例:
#include <iostream> // std::cout
#include <type_traits> // std::is_same
template<class T1, class T2>
void print_is_same() {
std::cout << std::is_same<T1, T2>() << '\n';
}
int main() {
std::cout << std::boolalpha;
print_is_same<int, int>();
print_is_same<int, int &>();
print_is_same<int, int &&>();
print_is_same<int, std::remove_reference<int>::type>(); // Why not typename std::remove_reference<int>::type ?
print_is_same<int, std::remove_reference<int &>::type>();// Why not typename std::remove_reference<int &>::type ?
print_is_same<int, std::remove_reference<int &&>::type>();// Why not typename std::remove_reference<int &&>::type ?
}
type
特性中的std::remove_reference
是从属类型。
可能的实施方式
template< class T > struct remove_reference {typedef T type;};
template< class T > struct remove_reference<T&> {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};
但是为什么不使用typename std::remove_reference</*TYPE*/>::type
?
答案 0 :(得分:22)
type
特性中的std::remove_reference
是从属类型。
否,他们不是dependent names。模板参数已明确指定为int
,int&
和int&&
。因此,此时类型是已知的。
另一方面,如果您将std::remove_reference
与模板参数一起使用,例如
template <typename T>
void foo() {
print_is_same<int, typename std::remove_reference<T>::type>();
}
然后,您必须使用typename
来确定std::remove_reference<T>::type
是一种类型,因为您的表达式现在取决于模板参数T
。
答案 1 :(得分:5)
简而言之,您需要typename
来确保编译器能够
std::remove_reference<int>::type
真的是一种类型。让我们考虑其他模板
template <typename T>
struct foo {
using type = int;
};
foo::type
是一种类型。但是,如果有人提供类似
template <> struct foo<int> {
int type;
};
现在type
不是类型而是int
。现在,当您在模板中使用foo时:
template <typanem T>
struct bar {
using type = typename foo<T>::type;
};
您必须确保编译器确实foo<T>::type
是一种类型,而不是其他类型,因为仅查看bar
(和主模板foo
),编译器就无法知道。
但是,在您的main
中,std::remove_reference<int>::type
并不依赖于模板参数,因此编译器可以轻松地检查它是否为类型。
答案 2 :(得分:0)
关键字 typename 用于帮助编译器解析源。 它指出id是类型名,而不是变量名或方法名。 但是在类似上述情况的情况下,编译器可以自行解决,因此不需要此关键字。