Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么时候开始;typename";有必要吗?_C++_Templates_Syntax_Typename - Fatal编程技术网

C++ 什么时候开始;typename";有必要吗?

C++ 什么时候开始;typename";有必要吗?,c++,templates,syntax,typename,C++,Templates,Syntax,Typename,可能重复: 考虑以下代码: template<class K> class C { struct P {}; vector<P> vec; void f(); }; template<class K> void C<K>::f() { typename vector<P>::iterator p = vec.begin(); } 模板 C类{ 结构P{}; 向量vec; 无效f(); }; 模板v

可能重复:

考虑以下代码:

template<class K>
class C {
    struct P {};
    vector<P> vec;
    void f();
};

template<class K> void C<K>::f() {
    typename vector<P>::iterator p = vec.begin();
}
模板
C类{
结构P{};
向量

vec; 无效f(); }; 模板void C::f(){ typename向量

::迭代器P=vec.begin(); }

为什么在这个例子中需要“typename”关键字?
是否还有其他必须指定“typename”的情况?

每当类型名依赖于模板参数时,都需要使用typename关键字(这样编译器就可以“知道”标识符(类型或值)的语义,而不必在第一次传递时有完整的符号表)


在使用通用模板参数时,lone typename关键字也可能很有用,但含义不同,且不太常见:

#包括
#包括
#包括
模板
结构容器测试
{
typedef容器IntContainer;
typedef容器StringContainer;
//
void DoTests()
{
ints集装箱ints;
字符串容器字符串;
//…等等
}
};
int main()
{
集装箱测试t1;
集装箱测试t2;
t1.DoTests();
t2.DoTests();
}

需要
类型名
关键字,因为
迭代器
p
的依赖类型。编译器无法猜测迭代器是引用了一个值还是一个类型,因此除非您大叫
typename
,否则它将假定它是一个值。在类型或值都有效的上下文中,只要存在依赖于模板参数的类型,就需要它。例如,由于基类必须是类型,因此不需要as基类
typename


在同一主题上,有一个
template
关键字用于让编译器知道某个依赖名称是一个模板函数而不是一个值。

简短回答:每当引用作为依赖名称的嵌套名称时,即嵌套在具有未知参数的模板实例中

详细回答:C++中有三层实体:值、类型和模板。所有这些都可以有名称,而名称本身并不能告诉您它是实体的哪一层。相反,关于名称实体性质的信息必须从上下文中推断出来

如果无法进行此推断,则必须指定:

template <typename> struct Magic; // defined somewhere else

template <typename T> struct A
{
  static const int value = Magic<T>::gnarl; // assumed "value"

  typedef typename Magic<T>::brugh my_type; // decreed "type"
  //      ^^^^^^^^

  void foo() {
    Magic<T>::template kwpq<T>(1, 'a', .5); // decreed "template"
    //        ^^^^^^^^
  }
};
用法:

int main()
{
  A<int> a;
  a.foo();

  return Magic<signed char>::kwpq<float>(2, 3);  // no disambiguation here!
}
intmain()
{
A A;
a、 foo();
return Magic::kwpq(2,3);//这里没有消歧!
}

我以前从来都不知道“孤独的typename”,太酷了@Nils:<代码> const > C++无效。谢谢解释。但我不能理解最后一件事:由于名称
Magic::kwpq
依赖于模板参数
t
,这将在两阶段查找的第二阶段解决,对吗?那么,为什么编译器当时不能检查(当他能够确定
kwpq
是一个模板还是一个类型或任何东西时)名称是否根据其实体层正确使用?@PaoloM:class template
a
的成员函数的定义必须在第一阶段进行解析,因此,您需要消除歧义才能使语法有意义。在第二阶段,我们检查具体类型
T
的实例化
Magic
是否实际有一个成员
kwpq
,该成员是具有适当签名的函数。(感谢您的编辑!)
template <typename T> struct Magic
{
  static const T                    gnarl;
  typedef T &                       brugh;
  template <typename S> static void kwpq(int, char, double) { T x; }
};
template <> struct Magic<signed char>
{
  // note that `gnarl` is absent
  static constexpr long double brugh = 0.25;  // `brugh` is now a value
  template <typename S> static int kwpq(int a, int b) { return a + b; }
};
int main()
{
  A<int> a;
  a.foo();

  return Magic<signed char>::kwpq<float>(2, 3);  // no disambiguation here!
}