Frage

Wenn ich eine normale (schwache) Aufzählung habe, kann ich die aufgezählten Werte als nicht typisierte Vorlagenparameter verwenden, z. B.:

enum { Cat, Dog, Horse };

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

und nennen Sie es: magic<Cat>(t)

Soweit ich sehen kann, habe ich, wenn ich eine stark typisierte Aufzählung habe und den Aufzählungstyp nicht fest codieren möchte, Folgendes:

enum class Animal { Cat, Dog, Horse };

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

und jetzt muss ich schreiben: magic<Animal, Animal::Cat>(t), der überflüssig erscheint.

Gibt es eine Möglichkeit zu vermeiden, dass sowohl die Aufzählungsklasse als auch der Wert kurz vor eingegeben werden?

#define MAGIC(E, T) (magic<decltype(E), E>(T));

War es hilfreich?

Lösung

Sie können dies so tun, wenn Sie C ++ 17 verwenden können

#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

Andere Tipps

Es tut mir leid, das muss ich Ihnen sagen

Es ist nicht möglich

Nehmen Sie das Makro, fügen Sie es in einen beängstigenden benannten Header ein und schützen Sie es vor dem Bereinigungsskript Ihres Kollegen.Auf das Beste hoffen.

Wenn Sie nur am Wert des enums und nicht am Typ interessiert sind, sollten Sie in der Lage sein, den Wert mithilfe einer constexpr-Funktion in eine Ganzzahl zu konvertieren, ohne den Typnamen zu wiederholen.

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

Wie bereits von anderen erwähnt, funktioniert dies jedoch nicht, wenn Sie dies auch vom Typ abhängig machen möchten.

Diese Frage hat eine akzeptierte Antwort (positiv bewertet).

Während ich meinen eigenen Code überarbeitete, fand ich eine vollständigere Lösung:

Schritt 1: Verwenden von Code, den ich geschrieben habe:

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

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top