Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template classes vs Private inheritance

Why would some compilers insist on qualifying members public members of template base class while the not requiring the same for non-template class? Please look at the following code listings:

Template class:

#include <iostream>

using namespace std;

template <class T>
class TestImpl {
public: // It wont make a difference even if we use a protected access specifier here
    size_t vval_;
    TestImpl(size_t val = 0) : vval_(val) { }
};

template <class T>
class Test : public TestImpl<T> {
public:
    Test(size_t val) : TestImpl<T>(val) {
        cout << "vval_ : " << vval_ << endl; // Error: vval_ was not declared in this scope
        //! cout << "vval_ : " << TestImpl<T>::vval_ << endl; // this works, obviously
    }
};

int main() {
    Test<int> test1(7);

    return 0;
}

Non-template class:

#include <iostream>

using namespace std;

class TestImpl {
public: // It wont make a difference even if we use a protected access specifier here
    TestImpl(size_t val = 0) : vval_(val) {}
    size_t vval_;
};

class Test : public TestImpl {
public:
    Test(size_t val) : TestImpl(val) {
        cout << "vval_ : " << vval_ << endl;
    }
};

int main() {
    Test test1(7);

    return 0;
}

The significant difference between the above code listings is that while the first listing uses template classes, the second one doesn't.

Now, both listings will compile fine with Microsoft's Visual Studio Compiler (cl) but the first listing WONT compile with both the Digital Mars Compiler (dmc) and Minimalist GNU for Windows (MinGW - g++) compiler. I will get an error like "vval_ was not declared in the scope" - an error I obviously understand what it means.

If I qualify access to the TestImpl's public variable vval_ using TestImpl<T>::vval_ the code works. In the second listing, the compilers do not complain when the derived class accesses the base class' vval_ variable without qualifying it.

With regard to the two compilers and possibly others, my question would be why I should be able to directly access (without qualifying) vval_ variable directly from a non-template class inheriting from a non-template class, while I cant do the same from a template class inheriting from a template class?

like image 947
John Gathogo Avatar asked Mar 25 '26 10:03

John Gathogo


1 Answers

You have to qualify vval_ with the TestImpl<T> to tell the compiler that it depends on the actual type of T in Test<T> (there might be some partial/explicit specializations of TestImpl<T> declared before the definition of Test<T> and it's instantiation that will change the meaning of vval_ in that context. In order to make the compiler aware of that, you have to tell that vval_ is (template parameter) dependent.

See also http://gcc.gnu.org/onlinedocs/gcc/Name-lookup.html

like image 131
MichalR Avatar answered Mar 27 '26 02:03

MichalR



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!