为什么在以下情况下不需要对依赖类型使用 typename?
Why is it not required to use typename for dependent types in the following case?
我一直在阅读有关删除类型引用的内容,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 ?
}
std::remove_reference
特征中的 type
是依赖类型。
可能的实现
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
呢?
The type
s in the std::remove_reference
traits are dependent types.
不,他们不在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
.
简而言之,您需要 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
不依赖于模板参数,因此编译器可以很容易地检查它是否是一个类型。
关键字typename用于帮助编译器解析源代码。
它指向的id是一个类型名,而不是变量名或方法名。
但是像上面这样的情况,编译器可以自己判断,所以不需要这个关键字。
我一直在阅读有关删除类型引用的内容,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 ?
}
std::remove_reference
特征中的 type
是依赖类型。
可能的实现
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
呢?
The
type
s in thestd::remove_reference
traits are dependent types.
不,他们不在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
.
简而言之,您需要 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
不依赖于模板参数,因此编译器可以很容易地检查它是否是一个类型。
关键字typename用于帮助编译器解析源代码。 它指向的id是一个类型名,而不是变量名或方法名。 但是像上面这样的情况,编译器可以自己判断,所以不需要这个关键字。