当前位置:  开发笔记 > 编程语言 > 正文

GCC问题:使用依赖于模板参数的基类成员

如何解决《GCC问题:使用依赖于模板参数的基类成员》经验,为你挑选了4个好方法。

以下代码不使用gcc编译,但使用Visual Studio编译:

template  class A {
public:
    T foo;
};

template  class B: public A  {
public:
    void bar() { cout << foo << endl; }
};

我收到错误:

test.cpp:在成员函数'void B :: bar()'中:

test.cpp:11:错误:在此范围内未声明'foo'

但它应该是!如果我换bar

void bar() { cout << this->foo << endl; }

然后它确实编译,但我不认为我必须这样做.GCC在这里遵循C++官方规范中的某些内容,还是仅仅是一个怪癖?



1> Vincent Robe..:

大卫·乔伊纳有历史,这就是原因.

编译时的问题B是它的基类A在编译器中是未知的,是一个模板类,所以编译器无法知道基类中的任何成员.

早期版本通过实际解析基本模板类做了一些推断,但ISO C++声明这种推断可能导致不应该存在的冲突.

在模板中引用基类成员的解决方案是使用this(像您一样)或专门命名基类:

template  class A {
public:
    T foo;
};

template  class B: public A  {
public:
    void bar() { cout << A::foo << endl; }
};

有关gcc手册的更多信息.


一方面,这种做法是有道理的.但另一方面,感觉真的很蹩脚.在模板实例化之前,编译器不需要*知道`foo`引用了什么,此时它应该能够识别`A`中的`foo`成员.C++有太多这些奇怪的角落案例.

2> Derek Park..:

哇.C++永远不会因为它的古怪而让我感到惊讶.

在模板定义中,非限定名称将不再找到依赖库的成员(由C++标准中的[temp.dep]/3指定).例如,

template  struct B {
  int m;
  int n;
  int f ();
  int g ();
};
int n;
int g ();
template  struct C : B {
  void h ()
  {
    m = 0; // error
    f ();  // error
    n = 0; // ::n is modified
    g ();  // ::g is called
  }
};

您必须使名称依赖,例如通过在其前面加上this->.这是C :: h的更正定义,

template  void C::h ()
{
  this->m = 0;
  this->f ();
  this->n = 0
  this->g ();
}

作为替代解决方案(遗憾的是不向后兼容GCC 3.3),您可以使用声明而不是this->:

template  struct C : B {
  using B::m;
  using B::f;
  using B::n;
  using B::g;
  void h ()
  {
    m = 0;
    f ();
    n = 0;
    g ();
  }
};

这只是各种疯狂.谢谢,大卫.

这是他们所指的标准[ISO/IEC 14882:2003]的"temp.dep/3"部分:

在类模板的定义或类模板的成员中,如果类模板的基类依赖于模板参数,则在类的定义时,在非限定名称查找期间不会检查基类作用域.模板或成员或在类模板或成员的实例化期间.[例:

typedef double A; 
template class B { 
    typedef int A; 
}; 
template struct X : B { 
    A a; // a has typedouble 
}; 

A定义中的类型名称X绑定到全局命名空间范围中定义的typedef名称,而不绑定到基类中定义的typedef名称B.] [例子:

struct A { 
    struct B { /* ... */ }; 
    int a; 
    int Y; 
}; 
int a; 
template struct Y : T { 
    struct B { /* ... */ }; 
    B b; //The B defined in Y 
    void f(int i) { a = i; } // ::a 
    Y* p; // Y 
}; 
Y ya; 

成员A::B,A::aA::Y模板参数A不会影响名称的绑定Y.]



3> David Joyner..:

这在gcc-3.4中有所改变.C++解析器在该版本中变得更加严格 - 按照规范,但对于具有传统或多平台代码库的人来说仍然有点烦人.



4> Matt Price..:

C++在这里不能假设的主要原因是基本模板可以在以后专门用于某种类型.继续原始的例子:

template<>
class A {};

B x; 
x.bar();//this will fail because there is no member foo in A

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有