Pergunta

Se eu tiver uma enumeração normal (fraca), posso usar seus valores enumerados como parâmetros de modelo não-tipo, assim:

enum { Cat, Dog, Horse };

template <int Val, typename T> bool magic(T &t)
{
    return magical_traits<Val>::invoke(t);
}

e chame-o de: magic<Cat>(t)

até onde eu posso ver, se eu tiver uma enumeração fortemente tipada e não quiser codificar o tipo de enumeração, eu termino com:

enum class Animal { Cat, Dog, Horse };

template <typename EnumClass, EnumClass EnumVal, typename T> bool magic(T &t)
{
    return magical_traits<EnumVal>::invoke(t);
}

e agora tenho que escrever: magic<Animal, Animal::Cat>(t), que parece redundante.

Existe alguma maneira de evitar digitar a classe enum e o valor, exceto

#define MAGIC(E, T) (magic<decltype(E), E>(T));
Foi útil?

Solução

Você pode fazer assim, se puder usar 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>();
}

demonstração: http://coliru.stacked-crooked.com/a/9ac5095e8434c9da

Outras dicas

Sinto muito, devo lhe dizer isso

Não é possível

Pegue a macro, coloque-a em um cabeçalho com nome assustador e proteja-a do script de limpeza de seu colega.Espere o melhor.

Se você está interessado apenas no valor do enum, e não em seu tipo, você deve ser capaz de usar uma função constexpr para converter o valor em um inteiro, evitando repetir o nome do tipo.

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

No entanto, como já foi apontado por outros, se você quiser fazer isso depender do tipo também, não funcionará.

Esta pergunta tem uma resposta aceita (votada).

Enquanto refatorava meu próprio código, descobri uma solução mais completa:

Etapa 1: usando o código que estava escrevendo:

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

Etapa 2: código do cliente:

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>;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top