Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template pattern matching

Consider this class template:

template <typename T1, typename T2, bool B>
class SomeClass { };

Now, I'd like to provide two implementations based on B==true and B==false. That is, I'd like to say something like:

template <ANYTHING, ANYTHING, true> class SomeClass {
// First implementation
};

template <ANYTHING, ANYTHING, false> class SomeClass {
// Second implementation
};

How can this be done in C++(11)?

like image 600
Cartesius00 Avatar asked Nov 22 '12 14:11

Cartesius00


2 Answers

With partial specialization:

// primary
template<typename X, typename Bool>
struct Foo;

template<typename X>
struct Foo<X, std::true_type> {};

template<typename X>
struct Foo<X, std::false_type> {};

// use
Foo<X, std::true_type> x;

I use a type-wrapper for bool, but you can also do that with non-type template parameters:

// primary
template<typename, bool>
struct Foo;

template<typename X>
struct Foo<X, true> {};

template<typename X>
struct Foo<X, false> {};

// use
Foo<X, true> x;

Sometimes you can compute the value used for partial specialization with meta-programming in the default argument:

// primary
template<typename X, typename is_integral_ = std::is_integral<X>::type>
struct Foo;

This makes the configuration variable overridable by user choice.

struct my {};
Foo<my, std::true_type> x;

To prevent that, dispatch through inheritance:

// primary, where Foo_impl is any of the above
template<typename X>
struct Foo : public Foo_impl<X> {};
like image 90
pmr Avatar answered Oct 13 '22 17:10

pmr


It's called partial specialization:

template <typename T1, typename T2> class SomeClass<T1 ,T2, true> {
// First implementation
};

template <typename T1, typename T2> class SomeClass<T1, T2, false> {
// Second implementation
};

As the name indicates it is related to (full) specialization which looks like this:

template <> class SomeClass<int, char, false> {
// dedicated version for T1=int, T2=char, B=false
};

Note that if most of the implementation is the same, you can also write a single generic version, where only that code which depends on the bool argument is delegated to a trait class. In this case, the trait class would be fully-specialized on a single argument.

like image 29
Useless Avatar answered Oct 13 '22 15:10

Useless