template argument deduction with strongly-typed enumerations

前端 未结 4 1184
迷失自我
迷失自我 2020-12-13 14:11

If I have a normal (weak) enumeration, I can use its enumerated values as non-type template parameters, like so:

enum { Cat, Dog, Horse };

template 

        
相关标签:
4条回答
  • 2020-12-13 14:37

    This question has an accepted answer (upvoted).

    While refactoring my own code, I figured out a more complete solution:

    Step 1: using code I was writing:

    template<typename V, typename EnumClass, EnumClass Discriminator>
    class strong_type final // type-safe wrapper for input parameters
    {
        V value;
    public:
        constexpr explicit strong_type(V x): value{x} {}
        constexpr auto get() const { return value; }
    };
    

    Step 2: client code:

    enum class color { red, green, blue, alpha };
    
    // the part OP was asking about:
    template<color C>
    using color_channel = strong_type<std::uint8_t, color, C>;
    
    using red = color_channel<color::red>; // single argument here
    using green = color_channel<color::green>;
    using blue = color_channel<color::blue>;
    using alpha = color_channel<color::alpha>;
    
    0 讨论(0)
  • 2020-12-13 14:39

    If you're only interested in the enum's value, and not its type, you should be able to use a constexpr function to convert the value to an integer, avoiding repeating the type name.

    enum class Animal { Cat, Dog, Horse };
    
    template <typename T> constexpr int val(T t)
    {
        return static_cast<int>(t);
    }
    
    template <int Val, typename T> bool magic(T &t)
    {
        return magical_traits<Val>::invoke(t);
    }
    
    magic<val(Animal::Cat)>(t);
    

    However, as pointed out already by others, if you want to make this depend on the type as well, it will not work.

    0 讨论(0)
  • 2020-12-13 14:41

    I'm sorry, I have to tell you that

    It is not possible

    Take the macro, put it into a scary named header and protect it from your colleague's cleanup script. Hope for the best.

    0 讨论(0)
  • 2020-12-13 14:56

    You can do it like this, if you can use C++17

    #include <type_traits>
    
    enum class Animal { Cat, Dog, Horse };
    
    template <typename EnumClass, EnumClass EnumVal> 
    void magic_impl()
    {
        static_assert(std::is_same_v<EnumClass, Animal>);
        static_assert(EnumVal == Animal::Cat);
    }
    
    template <auto EnumVal>
    void magic()
    {
        magic_impl<decltype(EnumVal), EnumVal>();
    }
    
    int main()
    {
        magic<Animal::Cat>();
    }
    

    demo: http://coliru.stacked-crooked.com/a/9ac5095e8434c9da

    0 讨论(0)
提交回复
热议问题