如何为一系列整数值专门化C ++模板?

时间:2012-06-13 16:24:57

标签: c++ templates

有没有办法根据一系列值而不是一个值进行模板专业化?我知道以下代码不是有效的C ++代码,但它显示了我想要做的事情。我正在为8位机器编写代码,因此使用整数和字符的速度有所不同。

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
};

4 个答案:

答案 0 :(得分:47)

尝试std::conditional

#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;
};

如果您的编译器还不支持C ++ 11的这一部分,那么boost libraries.

就相当于

然后,你可以轻松推出自己的产品(功劳归功于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;
}; 

答案 1 :(得分:33)

使用额外的默认bool参数:

// 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
};

答案 2 :(得分:7)

另一种可能的选择:

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 example

答案 3 :(得分:0)

我讨厌处理类型有多混乱,所以我提出一些更简单的方法,利用constexpr。当不需要变化类型时,此变体允许不同的行为,并且需要适应范围而不仅仅是值的一侧:

template<bool> struct If;

constexpr bool InClosedRange(std::size_t Value, std::size_t Lower, std::size_t Upper)
{
    return (Lower <= Value) && (Value <= Upper);
}

// Usage:
template<size_t Width, If<true>>
class Foo;

template<size_t Width, If<InClosedRange(Width, 1, 41)>>
class Foo { /* ... */ };

template<size_t Width, If<InClosedRange(Width, 42, 142)>>
class Foo { /* ... */ };

灵感来自:https://stackoverflow.com/a/9516959/929315