43 votes

Comment puis-je me spécialise en C++ template pour une plage de valeurs?

Est-il possible d'avoir un modèle de spécialisation basée sur une gamme de valeurs au lieu d'une seule? Je sais que le code suivant n'est pas valide code C++, mais il montre ce que je voudrais faire. Je suis en train d'écrire le code pour un 8-bits de la machine, donc il y a une différence de vitesse pour l'utilisation de services de renseignements et de caractères.

template<unsigned SIZE>
class circular_buffer {
   unsigned char buffer[SIZE];
   unsigned int head; // index
   unsigned int tail; // index
};

template<unsigned SIZE <= 256>
class circular_buffer {
   unsigned char buffer[SIZE];
   unsigned char head; // index
   unsigned char tail; // index
};

49voto

jrok Points 30472

Essayez std::conditionnel:

#include <type_traits>

template<unsigned SIZE>
class circular_buffer {

    typedef typename
        std::conditional< SIZE < 256,
                          unsigned char,
                          unsigned int
                        >::type
        index_type;

    unsigned char buffer[SIZE];
    index_type head;
    index_type tail;
};

Si votre compilateur ne supporte pas encore cette partie de C++11, il n'y a d'équivalent dans les bibliothèques boost.

Là encore, il est facile de rouler votre propre (crédit va à KerrekSB):

template <bool, typename T, typename F>
struct conditional {
    typedef T type;
};

template <typename T, typename F>  // partial specialization on first argument
struct conditional<false, T, F> {
    typedef F type;
}; 

33voto

Utiliser un supplément de souffrance bool paramètre:

// primary template handles false
template<unsigned SIZE, bool IsSmall = SIZE <= 256>
class circular_buffer {
   unsigned char buffer[SIZE];
   unsigned int head; // index
   unsigned int tail; // index
};

// specialization for true
template<unsigned SIZE>
class circular_buffer<SIZE, true> {
   unsigned char buffer[SIZE];
   unsigned char head; // index
   unsigned char tail; // index
};

7voto

cdhowie Points 62253

Une autre option possible:

template <unsigned SIZE>
struct offset_size {
    typedef typename offset_size<SIZE - 1>::type type;
};

template <>
struct offset_size<0> {
    typedef unsigned char type;
};

template <>
struct offset_size<257> {
    typedef unsigned int type;
};

template<unsigned SIZE>
class circular_buffer {
   unsigned char buffer[SIZE];
   typename offset_size<SIZE>::type head; // index
   typename offset_size<SIZE>::type tail; // index
};

(Ideone exemple)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X