使用作为模板参数提供的基类成员而不使用限定符

时间:2015-10-09 19:08:41

标签: c++

此代码有效:

struct Defs
{
    static const int a = 1;
    int b{};
    void g() {}
};

struct Bob : Defs
{
    void f()
    {
        cout << a << "\n";
        cout << b << "\n";
        g();
    }
};

int main()
{
    Bob b;
    b.f();
}

但是这段代码没有:

struct Defs
{
    static const int a = 1;
    int b{};
    void g() {}
};

template<class D>
struct Bob : D
{
    void f()
    {
        cout << a << "\n";
        cout << b << "\n";
        g();
    }
};

int main()
{
    Bob<Defs> b;
    b.f();
}

错误:

prog.cpp: In member function 'void Bob<D>::f()':
prog.cpp:16:11: error: 'a' was not declared in this scope
   cout << a << "\n";
           ^
prog.cpp:17:11: error: 'b' was not declared in this scope
   cout << b << "\n";
           ^
prog.cpp:18:5: error: there are no arguments to 'g' that depend on a template parameter, so a declaration of 'g' must be available [-fpermissive]
   g();
     ^
prog.cpp:18:5: note: (if you use '-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)

但是,如果我执行以下操作,它会起作用:

template<class D>
struct Bob : D
{
    void f()
    {
        cout << D::a << "\n";
        cout << D::b << "\n";
        D::g();
    }
};

是否可以让类使用作为模板参数提供的基类的成员,而不限定它们?我问的原因是因为这样做可以让我在没有很多改变的情况下重构一些代码。

可以假设用作模板参数的类型具有所有这些成员,否则编译失败是可接受的。

2 个答案:

答案 0 :(得分:5)

简介

您收到错误是因为模板参数上的基类是依赖,这并不太令人惊讶,因为基类是直接的使用模板参数

错误诊断来自于以下事实:不同的模板参数可能会在类中产生明显不同的行为;如果传入的 template-parameter 没有某个成员,该怎么办?那么我们要在全球范围内查找一些内容吗?

明确声明您要访问this

的成员

你是说你想要访问基类的成员而不对他们进行限定,如果我从字面上理解你,我会说你可以使用this->member-name - 但我怀疑这一点就你所写的关于重构的内容而言,你就是这样。

struct A { 
  int m;
};
template<class T>
struct B : T { 
  void func () {
    this->m = 1;
  }
};
int main () {
  B<A> {}.func (); 
}

依赖基类

中输入名称

另一种选择是明确声明您希望基类中的某些名称可以直接使用{ - 1}}中的某些名称,如下所示:

using

以上可以理解为; &#34;亲爱的编译器,无论我在哪里引用template<class T> struct B : T { using T::m; void func () { m = 1; } }; 我都希望您使用m&#34; 中的那个。

但我想破解这个问题;如何!?

好的,介绍一个非依赖库,并将引用引入您真正想要的数据。如果您知道要为每个T提供哪些名称,这将有效。

你甚至可以扩展这个hack来自动推断出那些成员的类型,但这远远不是问题的范围。

T
#include <iostream>

struct A {
  int n;
  int m;

  void print () {
    std::cout << m << std::endl;
  }
};
struct Hack {
  template<class T>
  Hack (T* hck) : m (hck->m), n (hck->n) { }
  int& m;
  int& n;
};
template<class T>
struct B : T, Hack {
  B () : Hack (static_cast<T*> (this)) { }

  void func () {
    m = 123;
  }
};

您可以找到正在运行的示例here。警告的话;我本人永远不会这样做,但正如你所看到的那样,你可以通过一点间接来做你所要求的事情。

答案 1 :(得分:3)

您可以添加:

using D::a;
using D::b;
using D::g;

Bob来解决您的范围问题。

Here是对此问题的全面概述。老实说,它不是C ++的一个角落,不应该存在,但是,没有语言是完美的= P