模板继承:没有依赖于模板参数的参数。

4

在编译以下代码时,我遇到了这个错误。经过一些研究和阅读不同情况下相似的错误后,我找到了所需的解决方案。但是,我并没有完全理解错误和修复的根本原因。

template <typename T>
class TestA {
    int a;
    T temp;

protected:
    int b; 

public: 
    int c;

    TestA(T te): a{10}, b{20}, c{30}, temp{te} {}

    int geta(){ return a; }
    int getb(){ return b; }
    int getc(){ return c; }
};

template <typename T>
class TestB {
    int atb;
    T tempb;

protected:
    int btb; 

public: 
    int ctb;

    TestB(T te) atb{10}, btb{20}, ctb{30}, tempb{te} {}
};

template <typename T>
class TestInh : public TestA<T>, public TestB<T> {
    int aa;
    T temptemp;

protected:
    int bb; 
    int b;

public: 
    int cc;

    TestInh(T te) : TestA<T>{te}, TestB<T>{te}, bb{10000}, b{-1000} {}

    int get_total() {
        // The error happens here!
        return geta();
    }
};

int main(int argc, char const *argv[]) {
    char text = 'a';
    TestInh<char> test(text);

    //std::cout << test.geta() << std::endl;
    std::cout << test.get_total() << std::endl;
    //std::cout << test.c << std::endl;
    return 0;
}

编译此代码时,我遇到了以下错误:

testtemplate.cc: In member function ‘int TestInh<T>::get_total()’:
testtemplate.cc:54:32: error: there are no arguments to ‘geta’ that depend on a template parameter, so a declaration of ‘geta’ must be available [-fpermissive]
int get_total() {return geta();}
                            ^
testtemplate.cc:54:32: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)

通过调用this->geta()而不是仅仅调用geta()来解决此问题,但我并不完全理解为什么编译器不能自动解决。

有人能否解释一下原因?


它能够在VS2015中编译通过。 - GpG
@Gpg MSVC是错误的。不要依赖它对所有含有关键词template的事物进行处理。 - Guillaume Racicot
1个回答

14

当扩展依赖于模板参数的类时,this 就成为了一个相关名称。

问题在于,在执行两阶段名称查找时,编译器无法知道如何找到函数 geta()。他不知道它来自父类。因为模板特化是一件事情,TestA<int>TestA<double> 可能是两个完全不同的类,具有不同的函数和成员。

使用添加了 this 关键字后,编译器知道 geta() 必须是成员函数。

没有这个,它既可以是成员函数,也可以是非成员函数,或者是 TestB 的成员函数。

想象一个模板代码,根据一些模板条件,将从 TestATestB 调用函数 geta()。哎呀。编译器希望确保代码对于每个模板实例化都是一致的。

向编译器指出该函数存在为成员函数的另一种方法是添加 using 语句:

template <typename T> 
struct TestInh : TestA<T>, TestB<T> {
    // some code...
    
    using TestA<T>::geta;
    
    int get_total() {
        // works! With the above using statement,
        // the compiler knows that 'geta()' is
        // a member function of TestA<T>!
        return geta();
    }
};

写得很好,非常感谢。也许值得补充的是,即使只涉及单个基类,这种情况也可能发生,这最初让我感到困惑。 - antipattern

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接