Question

Si j'ai une énumération normale (faible), je peux utiliser ses valeurs énumérées comme paramètres de modèle non de type, comme ainsi:

enum { Cat, Dog, Horse };

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

Et appelez-le comme: magic<Cat>(t)

Pour autant que je puisse voir, si j'ai une énumération fortement typée et que je ne veux pas coder dur le type d'énumération, je me retrouve avec:

enum class Animal { Cat, Dog, Horse };

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

Et maintenant je dois écrire: magic<Animal, Animal::Cat>(t), ce qui semble redondant.

Existe-t-il un moyen d'éviter de taper à la fois la classe d'énumération et la valeur, à court

#define MAGIC(E, T) (magic<decltype(E), E>(T));
Était-ce utile?

La solution

Vous pouvez le faire comme ça, si vous pouvez utiliser 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>();
}

démo:http://coliru.stacked-crooked.com/a/9ac5095e8434c9da

Autres conseils

Je suis désolé, je dois te dire ça

Ce n'est pas possible

Prenez la macro, mettez-la dans une en-tête effrayante nommée et protégez-la du script de nettoyage de votre collègue. Espérons le meilleur.

Si vous êtes seulement intéressé par le enumValeur, et non son type, vous devriez pouvoir utiliser un constexpr Fonction pour convertir la valeur en un entier, en évitant de répéter le nom de type.

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

Cependant, comme le souligne déjà les autres, si vous voulez que cela dépend également du type, cela ne fonctionnera pas.

Cette question a un réponse acceptée (upvote).

En refactorisant mon propre code, j'ai trouvé une solution plus complète:

Étape 1: en utilisant le code que j'écrivais:

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

Étape 2: Code 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>;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top