Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect template parameters of base classes at compile time (for errors)?

I've been using the Curiously recurring template pattern The general code looks like this:

template <typename T> void genericFunction(T &);
template <typename T> struct Functionality {
    void genericMethod() {
        genericFunction(*((T *)this)) ;
    }
};

struct Klass : public Functionality<Klass> {};

void main() {
    Klass obj ;
    obj.genericMethod();
}

template <> void genericFunction<Klass>(Klass &obj) {
    //do stuff with Klass &obj here
}

I ran into an error today which cost me about 90 minutes of hair-pulling fustration, this error was caused by using an incorrect template parameter for my base class inheritance declaration, somewhat like so:

struct Klass : public Functionality<SomeOtherKlass> {}; //SomeOtherKlass wrong!!!

I'd like to enhance my code so that this mismatch between the derived class and the base class template parameter is detected (runtime, compile time, anytime :) ), is this even possible?, thanks.

like image 317
Gearoid Murphy Avatar asked Jan 08 '12 15:01

Gearoid Murphy


1 Answers

You could assert the relation in e.g. genericMethod() using Boost or C++11 features:

BOOST_STATIC_ASSERT(( boost::is_base_of<Functionality<T>, T>::value ));

... although that is assuming that the other class doesn't derive from Functionality<T> as well.

An alternative could be to assert the relation at runtime in test-builds:

template <typename T> struct Functionality {
#ifdef TEST_BUILD
    virtual ~Functionality() {}
#endif
    void genericMethod() {
#ifdef TEST_BUILD
        assert(dynamic_cast<T*>(this));
#endif
        genericFunction(*((T *)this)) ;
    }
};

Note that the test won't work inside constructors and destructors

like image 183
Georg Fritzsche Avatar answered Sep 29 '22 08:09

Georg Fritzsche