Reputation: 337
I am trying to make the following code work
template < class __derived, class __object = typename __derived::Object >
struct Base {
using Derived = __derived;
using Object = __object;
void function(Object o) { return Derived::function(s); }
}
//template < class __derived >
//struct Base {
// using Derived = __derived;
// using Object = typename Derived::Object;
// void function(Object o) { return Derived::function(s); }
//}
template < class __object >
struct Derived : public Base< Derived< __Object > > {
using Object = __object;
void function(Object o) { ... }
}
And i instantiate an object by declaring
Derived<double> obj;
Problem is, the compiler claims not to be able to find the symbol Object
inside the Derived
class while deducing the second template parameter for the Base
class. The same error is also generated by the commented version.
I am trying to do this under inspiration of Eigen3 code, particularly the CRTP (Curiously Recurring Template Pattern) they use in order to avoid use of virtual functions. Eigen3 actually uses a traits
class but I can't figure out how to imitate that for the present case.
Anyone has any suggestion about this? Thanks in advance!
Upvotes: 4
Views: 180
Reputation: 66922
Normally, if you want A to inherit from B, then B cannot know anything about A other than it's declaration:
template < class __object >
struct Derived;
Unfortunately, you want to get more, so you'll have to use a type trait:
template<class __derived>
struct Base_traits {
//using Object = ?????;
};
template<class __object>
struct Base_traits<Derived<__object>> {
using Object = __object; //note, this also can't inspect B.
};
The Base
class can inspect the Base_traits
all it wants, because the traits don't inspect B
at all.
template < class __derived, class __object = typename Base_traits<__derived>::Object >
struct Base {
using Derived = __derived;
using Object = typename Base_traits<__derived>::Object;
//or
using Object = __object;
Also, the syntax
void function(Object o) { return Derived::function(s); }
Won't work, because that notation cannot be used for upcasts, only downcasts. Ergo, you have to use static_cast
on the this
. Since that's vaguely ugly, I put it behind a function:
void foo(Object o) { self()->bar(o); }
private:
__derived* self() {return static_cast<__derived*>(this);}
const __derived* self() const {return static_cast<__derived*>(this);}
};
Full code: http://coliru.stacked-crooked.com/a/81595b0fcd36ab93
Upvotes: 4