c++ templates c++17 strong-typing template-deduction

c++ - Deducción de argumento de plantilla con enumeraciones fuertemente tipadas.



templates c++17 (4)

Esta pregunta tiene una respuesta aceptada (upvoted).

Mientras refactorizaba mi propio código, descubrí una solución más completa:

Paso 1: usando el código que estaba escribiendo:

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

Paso 2: código del 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>;

Si tengo una enumeración normal (débil), puedo usar sus valores enumerados como parámetros de plantilla no tipo, como por ejemplo:

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

y llámalo como: magic<Cat>(t)

por lo que puedo ver, si tengo una enumeración fuertemente tipada y no quiero codificar el tipo de enumeración, termino con:

enum class Animal { Cat, Dog, Horse }; template <typename EnumClass, EnumClass EnumVal, typename T> bool magic(T &t) { return magical_traits<EnumVal>::invoke(t); }

Y ahora tengo que escribir: magic<Animal, Animal::Cat>(t) , que parece redundante.

¿Hay alguna manera de evitar escribir tanto la clase enum como el valor, a menos que

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


Lo siento tengo que decirte eso

No es posible

Tome la macro, colóquela en un encabezado temible y protéjala del script de limpieza de su colega. Esperar lo mejor.


Puedes hacerlo de esta manera, si puedes 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>(); }

demostración: http://coliru.stacked-crooked.com/a/9ac5095e8434c9da


Si solo está interesado en el valor de la enum , y no en su tipo, debería poder usar una función constexpr para convertir el valor en un entero, evitando repetir el nombre 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);

Sin embargo, como ya lo señalaron otros, si quiere que esto también dependa del tipo, no funcionará.