歧义情况下的类型名解析

typename resolution in cases of ambiguity

本文关键字:类型 情况下 歧义      更新时间:2023-10-16

我在玩Visual Studio和模板。

考虑以下代码

struct Foo
{
  struct Bar
  {
  };
  static const int Bar=42;
};
template<typename T>
void MyFunction()
{
  typename T::Bar f;  
}
int main()
{
    MyFunction<Foo>();
    return 0;
}

当我在Visual Studio 2008和11中编译时,我得到以下错误

error C2146: syntax error : missing ';' before identifier 'f'

Visual Studio在这方面是否正确?代码是否违反了任何标准?

如果我把代码改成
struct Foo
{
  struct Bar
  {
  };
  static const int Bar=42;
};

void SecondFunction( const int& )
{
}
template<typename T>
void MyFunction()
{
  SecondFunction( T::Bar ); 
}
int main()
{
    MyFunction<Foo>();
    return 0;
}

编译时没有任何警告。在Foo::BLAH中,成员优于类型,以避免冲突?

编辑g++ 4.2.1的测试

struct Foo
{
  static const int Bar=42;
};

void SecondFunction(const int& x)
{
}
template<typename T>
void MyFunction()
{
  int x = Foo::Bar;
}
int main()
{
  MyFunction<Foo>();
  return 0;
}

编译好了。

struct Foo
{
  static const int Bar=42;
};

void SecondFunction(const int& x)
{
}
template<typename T>
void MyFunction()
{
  SecondFunction(T::Bar);
}
int main()
{
  MyFunction<Foo>();
  return 0;
}

给了我这些错误

未定义的符号:"Foo::Bar",引用自:在cck498aS.o中无效MyFunction()没有找到Ld:符号

在c++中,命名实体分为三个不同的本体层:类型模板

如果依赖名称是未知层,那么必须告诉编译器它是什么:

  • 如果你说typename,它是一个类型

  • 如果输入template,则为模板

因此,T::Bar作为MyFunction模板中的一个依赖名称,被自动假定为引用一个值,因此int成员Foo::Bar。另一方面,在第一个例子中,typename T::Bar确实指的是成员类型 Foo::Bar

您可以看到一个不为人所知的C兼容性规则的效果。在C中,与c++不同的是,如果将类型定义为struct Xenum X,则不需要将名称X引入相应的名称空间,而必须将类型引用为struct X。因此,在C中,您可以将'X'额外定义为不同的东西,而不会触发冲突的定义。现在在c++中,struct X确实将名称X引入了相应的作用域。因此,X的任何其他定义将被标记为双重定义。然而,能够在经常发生此问题的地方包含C头文件被认为是重要的。因此,引入了一个特殊的规则,无论何时您同时拥有X的(非typedef)类型定义和X的另一个定义,这都不会导致错误,但是X引用了非类型定义,并且为了获得类型定义,您必须在其前面加上相应的类型关键字(即struct X, emum Xclass X)。

在你的例子中,这意味着Foo包含一个名为class Bar的类型和一个名为Bar的静态const int,但没有名为Bar的类型。注意,这里不需要模板;一个简单的全局声明Bar::Foo foo;也应该失败。

相关文章: