Intro: The C++ standards differentiates between symbols name which depend on template arguments, and names which don't, that's called two-phase name lookup (see here). Non-dependant names are resolved as soon as possible when you define your template. On the other hand, dependant names are only resolved at template instanciation.
Example:
template<class T> struct Base {
    typedef T type;
    static const int n = 3;
    virtual int f() = 0;
    int f(int x) { return x * 2; }
};
// doesn't compile!
template<class T> struct Derived : Base<T> {
    type field;         // The compiler doesn't know Base<T>::type yet!
    int f() { return n; } // the compiler doesn't know n yet, and f(int) is maksed!
};
Currently, what I do is define Derived like this:
template<class T> struct Derived : Base<T> {
    typedef Base<T> Parent;
    typedef typename Parent::type type; // correct but
    using Parent::n;                    // boring, long
    using Parent::f;                    // and harder to maintain
    type field;
    int f() { return n; }
};
For me one of the main goal of object-oriented programming is reduce code duplication; this kind of defeat the purpose...
Question: is there another way do define Derived by using some syntax I don't know of or a smart trick? I'd love something like this:
template<class T> struct Derived : Base<T> {
    using Base<T>::*; // I promise I won't do strange specializations of Base<T>
    type field;
    int f() { return n; }
};
Edit Clarification: maybe I wasn't specific enough. Imagine you have a about ten typedefs / fields / functions in Base, and tens of derived classes with less than 5 lines of specific code for each. This means that most of the code will consist of repeated typedefs and using clauses, I know there's no way to totally avoid that, but I'm looking to minimize this repetitive code.
Thanks for any ideas making this easier to write and maintain!
T field;
That shouldn't be a problem; T is the template parameter itself, not a dependent name.
return n;
That is indeed a problem, since it's a dependent name and not known to be a member. The simplest solution is
return this->n;
Base<T>::n and Derived::n will also work, but I'd prefer not to duplicate the class names.
UPDATE
type field;
Unfortunately, there's no trick to access a dependent typename more simply than
typename Base<T>::type field;
Just hear me out a little
#include <string>
#include <iostream>
template<class T> struct Base {
    typedef T type;
    static const int n = 3;
    virtual int f() = 0;
    int f(int x) { return x * 2; }
};
// does compile
template< class T, template<typename> class Base = Base > 
struct Derived : Base<T> 
{
    typename Base<T>::type field; 
    int f() 
    {
        field = 200;
        return n;
    }
    int f(int x)
    {
        return Base<T>::f(x);
    }
};
int main()
{
    Derived<int> bss;
    std::cout << bss.f() << std::endl;
    std::cout << bss.f(50) << std::endl;
    std::cout << bss.field << std::endl;
    return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With