Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A Question on Template Specialization and the Resulting Code Duplication

Tags:

c++

templates

To specialize a class template, one has to redefine all of the member functions in the underlying base template (i.e. the unspecialized class template) even if they are expected to remain mostly unchanged. What are some of the accepted methods and "best practices" to avoid this code duplication?

Thanks.

like image 253
Ash Avatar asked Jan 31 '09 17:01

Ash


2 Answers

You can fully specialize a member selectively:

template<int N>
struct Vector {
    int calculate() { return N; }
};

// put into the .cpp file, or make inline!
template<>
int Vector<3>::calculate() { return -1; }

You do a full specialization. Meaning you cannot partial specialize it:

template<int N, int P>
struct Vector {
    int calculate() { return N; }
};

// WROOONG!
template<int N>
int Vector<N, 3>::calculate() { return -1; }

If you need that, you can use enable_if:

template<int N, int P>
struct Vector { 
    int calculate() { return calculate<P>(); }
private:
    // enable for P1 == 3
    template<int P1>
    typename enable_if_c<P1 == P && P1 == 3, int>::type
    calculate() { return -1; }

    // disable for P1 == 3
    template<int P1>
    typename enable_if_c<!(P1 == P && P1 == 3), int>::type
    calculate() { return N; }
};

An alternative approach is to split your stuff up (common stuff into a base class, and specialized stuff into the derived class) like Nick recommends.

I usually would take the second approach. But i prefer the first one if i don't need to partial specialize the functions.

like image 58
Johannes Schaub - litb Avatar answered Sep 30 '22 14:09

Johannes Schaub - litb


I've used base classes usually when this situation arises. Ie: put the common functionality in the base class, and derive the template class from it, then specialize the derived class with only the functions which are different.

like image 26
Nick Avatar answered Sep 30 '22 13:09

Nick