I have a template, template <typename T> class wrapper, that I would like to specialize based on the existence of typename T::context_type. If typename T::context_type is declared, then the constructors and assignment operator overloads of the wrapper<T> instantiation should accept a mandatory typename T::context_type parameter. Additionally, wrapper<T> objects would store “context” in the member data. If typename T::context_type does not exist, then the constructors and assignment operator overloads of wrapper<T> would take one less parameter and there would be no additional data member.
Is this possible? Can I get the following code to compile without changing the definitions of config1, config2, and main()?
#include <iostream>
template <typename T, bool context_type_defined = true>
class wrapper
{
public:
typedef typename T::context_type context_type;
private:
context_type ctx;
public:
wrapper(context_type ctx_)
: ctx(ctx_)
{
std::cout << "T::context_type exists." << std::endl;
}
};
template <typename T>
class wrapper<T, false>
{
public:
wrapper() {
std::cout << "T::context_type does not exist." << std::endl;
}
};
class config1 {
public:
typedef int context_type;
};
class config2 {
public:
};
int main()
{
wrapper<config1> w1(0);
wrapper<config2> w2;
}
Yes, it is possible. I have implemented such behavior in the past by using some metaprogramming tricks. The basic build blocks are:
BOOST_MPL_HAS_XXX_TRAIT_DEF, to define a metafunction predicate that will evaluate to a true type if the argument is of class type and has a nested type with a given name (context_type in your case).http://www.boost.org/doc/libs/1_47_0/libs/mpl/doc/refmanual/has-xxx-trait-def.html
Boost.EnableIf, to define the specializations based on the previously defined trait.http://www.boost.org/libs/utility/enable_if.html # See 3.1 Enabling template class specializations
Note that you may be able to get that behavior working directly with SFINAE, something like this may work:
However, I like the expressiveness of the solution based on traits and enable if.