Reputation: 10162
In the following code snippet:
#include <map>
template<class T>
struct Base {
typedef T U;
};
template<class T>
struct Derived: public Base<std::map<int,std::map<int,T>>> {
typedef typename Base<std::map<int,std::map<int,T>>>::U U; // ugly!
void F(U u) {};
};
int main(){}
the marked line is ugly and also contains duplicated information (if the type of the Base class parameters changes, this line must be changed too). However it is necessary to have such a repeated declaration, otherwise the code does not compile. Also, I would like to avoid to make a global typedef declaration...
Is there a solution to refer to a type defined in a template dependant base class?
Upvotes: 3
Views: 84
Reputation: 137330
The issue is that unqualified name lookup doesn't look into dependent base classes. So just qualify the name and tell the compiler that U
will be a member of Derived
:
void F(typename Derived::U u) {}
If you hate writing the whole thing out again and again, then use a new member alias:
using DU = typename Derived::U; // or typedef equivalent
Upvotes: 1
Reputation: 50540
If you can use at least C++11, you can combine a function declaration (no definition required here) and an using declaration as it follows:
#include <map>
#include<utility>
template<class T>
struct Base {
using U = T;
};
template<typename T>
typename Base<T>::U f(Base<T>);
template<typename T>
using BType = decltype(f(std::declval<T>()));
template<class T>
struct Derived: public Base<std::map<int,std::map<int,T>>> {
using U = BType<Derived>;
void F(U u) {};
};
int main(){}
Also note that typedef
s have been replaced by the using declarations as well.
Upvotes: 3
Reputation: 8994
You may pass a container type as template argument:
template<class T, class C = std::map<int,std::map<int,T>>>
struct Derived: public Base<C> {
typedef typename Base<C>::U U;
//...
};
P.S. same thing may be done in base class.
Upvotes: 4