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