24

如果我有一个普通(弱)枚举,我可以将其枚举值用作非类型模板参数,如下所示:

enum { Cat, Dog, Horse };

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

并将其称为:magic<Cat>(t)

据我所知,如果我有一个强类型枚举并且不想对枚举类型进行硬编码,我最终会得到:

enum class Animal { Cat, Dog, Horse };

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

现在我必须写: magic<Animal, Animal::Cat>(t),这似乎是多余的。

有什么办法可以避免同时输入枚举类和值,短

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

4 回答 4

26

你可以这样做,如果你可以使用 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>();
}

演示: http ://coliru.stacked-crooked.com/a/9ac5095e8434c9da

于 2017-11-25T09:30:55.667 回答
12

对不起,我必须告诉你

这不可能

获取宏,将其放入一个可怕的命名标头中,并保护它免受您同事的清理脚本的影响。希望最好的。

于 2012-02-22T18:28:27.537 回答
4

如果您只对enum的值而不是其类型感兴趣,您应该能够使用constexpr函数将值转换为整数,避免重复类型名称。

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

但是,正如其他人已经指出的那样,如果你想让它也依赖于类型,它就行不通了。

于 2012-02-22T19:05:49.983 回答
2

这个问题有一个公认的答案(赞成)。

在重构自己的代码时,我想出了一个更完整的解决方案:

第 1 步:使用我正在编写的代码:

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

第二步:客户端代码:

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>;
于 2017-11-25T08:52:54.410 回答