Domanda

Se ho un'enumerazione normale (debole), posso utilizzare i suoi valori enumerati come parametri di modello non di tipo, in questo modo:

enum { Cat, Dog, Horse };

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

e chiamalo come: magic<Cat>(t)

per quanto posso vedere, se ho un'enumerazione fortemente tipizzata e non voglio codificare il tipo di enumerazione, finisco con:

enum class Animal { Cat, Dog, Horse };

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

e ora devo scrivere: magic<Animal, Animal::Cat>(t), che sembra ridondante.

Esiste un modo per evitare di digitare sia la classe enum che il valore, a meno di

#define MAGIC(E, T) (magic<decltype(E), E>(T));
È stato utile?

Soluzione

Puoi farlo in questo modo, se puoi usare 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

Altri suggerimenti

Mi dispiace, devo dirtelo

Non è possibile

Prendi la macro, inseriscila in un'intestazione dal nome spaventoso e proteggila dallo script di pulizia del tuo collega.Sperare il meglio.

Se sei interessato solo al valore di enum e non al suo tipo, dovresti essere in grado di utilizzare una funzione constexpr per convertire il valore in un numero intero, evitando di ripetere il nome del 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);

Tuttavia, come già sottolineato da altri, se vuoi che anche questo dipenda dal tipo, non funzionerà.

Questa domanda ha una risposta accettata (voto positivo).

Durante il refactoring del mio codice, ho trovato una soluzione più completa:

Passaggio 1: utilizzo del codice che stavo scrivendo:

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

Passaggio 2: codice client:

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>;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top