How can I specialize a C++ template for a range of integer values?

后端 未结 4 844
离开以前
离开以前 2020-12-07 22:51

Is there a way to have a template specialization based on a range of values instead of just one? I know the following code is not valid C++ code but it shows what I would li

相关标签:
4条回答
  • 2020-12-07 23:20

    Use an extra defaulted bool parameter:

    // 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
    };
    
    0 讨论(0)
  • 2020-12-07 23:23

    I hate how messy dealing with types can be so I propose something a bit simpler, leveraging constexpr. This variant allows for differing behavior when a varying type is not required and addresses the need to fit within a range and not just one side of a value:

    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 { /* ... */ };
    

    Inspired by: https://stackoverflow.com/a/9516959/929315

    0 讨论(0)
  • 2020-12-07 23:45

    Another possible option:

    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)

    0 讨论(0)
  • 2020-12-07 23:46

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

    If your compiler doesn't yet support this part of C++11, there's equivalent in boost libraries.

    Then again, it's easy to roll your own (credit goes to 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;
    }; 
    
    0 讨论(0)
提交回复
热议问题