为什么在以下情况下不需要对依赖类型使用typename?

问题描述 投票:9回答:3

我一直在阅读有关删除类型为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

c++ c++11 templates typetraits dependent-name
3个回答
20
投票

type特性中的std::remove_reference是从属类型。

[不,这里不是dependent names。模板参数已明确指定为intint&int&&。因此,此时类型是已知的。

另一方面,如果您将std::remove_reference与模板参数一起使用,例如

template <typename T>
void foo() {
    print_is_same<int, typename std::remove_reference<T>::type>();
}

然后您必须使用typename来确定typename是一种类型,因为您的表达式现在取决于模板参数std::remove_reference<T>::type


5
投票

简而言之,您需要T以确保编译器具有以下功能:>

typename

确实是一种类型。让我们考虑其他模板

std::remove_reference<int>::type

这里template <typename T> struct foo { using type = int; }; 是一种类型。但是,如果有人按照

的方向提供专业化服务,该怎么办?
foo::type

现在template <> struct foo<int> { int type; }; 不是类型,而是type。现在,当您在模板中使用foo时:

int

您必须确保编译器确实template <typanem T> struct bar { using type = typename foo<T>::type; }; 是一种类型,而不是其他类型,因为仅查看foo<T>::type(和主模板bar),编译器就无法知道。

但是,在您的foo中,main不依赖于模板参数,因此编译器可以轻松地检查它是否为类型。


0
投票

关键字typename

© www.soinside.com 2019 - 2024. All rights reserved.