简体   繁体   中英

C++ specialized template class for a given type list

I am writing a kind of sparse matrix implementation, in fact there are 2 distinct implementations: one for light types (ie sizeof(T) <= sizeof(int64) and one for heavy types.

Depending on the sizeof(T) , I want to instantiate the corresponding class. I have first tested with a superclass that instantiate the HeavyType or the LightType implementation, but this requires both light and heavy to inherit from a common virtual BaseClass , and the generic call class uses one or the other (not very clean) in this way:

template <class T> class Generic{
public:
 Generic(){
   if (sizeof(T) > TRESHOLDVALUE)
    matrix_ = new HeavyType<T>();
   else
    matrix_ = new LightType<T>();
  }
private:
 matrix_ * BaseClass<T>;
};

This works, but it is not clean, and the virtualization in BaseClass slows down the execution...

I would like to write only one template class, and specialize it for several types, but I wonder: is it possibile to specialize against a particular value of sizeof(T) (ie equivalent to if (sizeof(T) <= sizeof(int64)) )? or for an array of possible types ( template <> class Matrix<arrayOfPossibleTypes> )?

I would like to avoid the re-writing of the class for int , bool , uint_32 , int32 , etc types.

Does anyone have an idea?

PS: Alternatively, I thought to a pre-compiler macro to select LightType or HeavyType class, but I think it's impossible to use sizeof() within a #if pre-compiler statement.

You're right that it's not possible to use sizeof in a preprocessor directive. And it's not needed, you can specialise on sizeof(T) just fine. In fact, you can specialise right on sizeof(T) <= sizeof(int64) :

template <class T>
class Generic{
private:
 MatrixType<T> matrix_;
};

template <class T, bool Light = sizeof(T) <= sizeof(int64)>
struct MatrixType;

template <class T>
struct MatrixType<T, true>
{
  //light matrix
};

template <class T>
struct MatrixType<T, false>
{
  //heavy matrix
};

One solution to this problem is std::enable_if (if you're using C++11) or boost::enable_if (if you're using an older standard). You can add an extra dummy template parameter to the template:

template <class T, typename Enable = void> class Generic;

template <class T>
class Generic<T, typename boost::enable_if_c<sizeof(T) > TRESHOLDVALUE>::type>
{
    // implementation for "heavy" class
    HeavyType<T> matrix_;
};

template <class T>
class Generic<T, typename boost::disable_if_c<sizeof(T) > TRESHOLDVALUE>::type>
{
    // implementation for "light" class
    LightType<T> matrix_;
};

This would be best if you actually need to have a different implementation for "light" versus "heavy." If all you're looking to do is change the type of the matrix_ member, and all the rest of your implementation stays the same, then you could use std::conditional (or its Boost equivalent, boost::mpl::if_c ).

With std::conditional , you may do something like:

template <class T> class Generic{
public:
    using MatrixType = typename std::conditional<(sizeof(T) > TRESHOLDVALUE), HeavyType<T>, LightType<T>>::type;
 Generic() {}
private:
 MatrixType  matrix_;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM