views:

57

answers:

2

Hi, I've been reading through this advice about template parameter constraints and was confused by this line:

template<class T> class Container : Derived_from<T,Mybase> {
    // ...
};

What's going on here? Is this just plain old inheritance being used to make the compiler examine Derived_from to perform the desired check? Why does this not lead to code being generated for Derived_from?

Thanks.

+1  A: 

Just look at the source for Derived_from, which is given in exactly the same URL you point to!

template<class T, class B> struct Derived_from {
    static void constraints(T* p) { B* pb = p; }
    Derived_from() { void(*p)(T*) = constraints; }
};

What code would you expect to be generated, besides that single initializer in Derived_from's constructor which should (one hopes) be easy for the compiler to optimize away? And the constraints static method just checks that a pointer to T can be correctly assigned to a pointer to B -- which of course should turn into a pure compile-time check that T is indeed derived from B, which is the constraint we desire.

Alex Martelli
+1  A: 

If the function that performs these checks just does those conversions that don't have any side effects, the optimizer will likely optimize that entire code away and will not generate any code for the function body. The only thing left will be the function symbol and a return instruction.

As it turns out (tested with GCC 4.5.1) not even the function's symbol need to be emitted. The compiler optimized out the address-taking, and then observed no other code in that file accesses the function, not emitting code for it. I think that's OK, because any other translation unit that needs that definition provides a definition by itself - so they don't depend on other translation units's compilation anyway.

Notice that using this method, the checks only trigger once you create an object of Container<T>. Otherwise, the constructor of Derived_from will never be implicitly instantiated and the checks are never done.

There are ways that completely get this done without any such dummy code, like boost::is_base_of.

Johannes Schaub - litb