【问题标题】:C++ Macro to use enum to access a type?使用枚举访问类型的 C++ 宏?
【发布时间】:2021-09-08 19:10:20
【问题描述】:

我不知道该怎么说。我有一个枚举,它基本上具有代表其他枚举类型的值。这是针对我正在研究的排序算法(就像购物页面上的过滤器一样)。

所以我说

enum Sorting { COLOR, PRICE };

enum Color { RED, BLUE };

有没有办法在我输入颜色并返回颜色类型的地方制作宏?

#define ENUM_ASSOCIATION(A, B)
#define ENUM_TYPE(A) //returns B from ENUM_ASSOCIATION

enum Sorting{ COLOR, PRICE };
ENUM_ASSOCIATION(COLOR, Color);

enum Color { RED, BLUE };

void someFunc()
{
    DoSomething<ENUM_TYPE(COLOR)>();
}

我是 C++ 预处理器的新手,并试图掌握它们。我觉得这应该不会太难完成,但我不确定如何去做,如果可能的话

编辑:

所以这就是我正在使用的。我没有编译错误,虽然我还不能测试它。使用这些宏声明的任何枚举都将使用 Assoc 结构,这可能会也可能不会导致问题。如果是这样,可能只需为每个宏添加一个 AliasName 参数并用它替换 Assoc。

// Allow use of ENUM_ASSOCIATION to create type aliases
#define DECLARE_ENUM_ASSOCIATION(T) template<T> struct Assoc;

// Creates a type alias, allowing to call ENUM_TYPE() and get the type V
// Remember to use only after both T and V have been declared previously
#define ENUM_ASSOCIATION(T, V) \
template<> \
struct Assoc<T> \
{\
    using type = V;\
};

#define ENUM_TYPE(T) Assoc<T>::type;

【问题讨论】:

  • 为什么不能只输入名称Color 来获取类型Color?为什么你需要一个不同的名字?
  • 这是一个过于简单的例子,我的大多数枚举值前面都有缩写(SO_COLOR、SO_PRICE 等),我必须将其用作我的团队想要保留的标准。有时我想创建一个名称与类型不同的枚举值
  • @DemonBismuth Imho 只有两个理由更喜欢枚举而不是枚举类:1. 它们可以隐式转换为基础类型,2. 您可以在 C 和 C++ 中使用它们。枚举的缺点是每个枚举常量都只是底层类型的常量,会污染命名空间。为常量名称添加前缀的真正原因是避免名称冲突。出于这个原因,我强烈建议不要违反现有枚举的这些命名约定。如果您引入了 C 代码中未使用的新枚举,请改用枚举类而不添加任何前缀。
  • 顺便说一句:使用枚举类,您甚至不需要为您描述的目的使用宏:enum class Color {Red, Blue}; ... using EnumType = decltype(Color::Red);
  • @fabian 是我想要达到的至少可能的目标吗?当然这可能更容易将它们命名为相同的(我将继续使它们成为枚举类),但我也想了解更多关于预处理器的信息。如果这不存在,我会停下来,但这种宏在许多不同的情况下可能很有用。我在虚幻引擎中工作,为了让引擎可以读取任何内容,我必须做大量的变通办法,这令人沮丧,这样的事情可能会在更多方面有所帮助。

标签: c++ filter enums macros preprocessor


【解决方案1】:

C++ 中的这种关联通常使用元函数来完成。例如

template <Sorting> struct Assoc;
template <> Assoc<COLOR> struct Assoc {using type = Color};

DoSomething<Assoc<COLOR>::type>();

当然你也可以#define ENUM_ASSOCIATION(COLOR, Color)来换行

  template <> Assoc<COLOR> struct Assoc {using type = Color};

#define ENUM_TYPE(COLOR) 包装

Assoc<COLOR>::type

   

【讨论】:

  • 这是否适用于枚举类(我在其他人的推荐下切换到这个)?把 ENUM_ASSOCIATION(Sorting::RED, Color) 说“Sorting::RED 不是类型名称。”
  • 你应该有ENUM_ASSOCIATION(Sorting::COLOR, Color),而不是Sorting::RED
  • 哎呀,我打错了。这个例子是枚举的一个过度简化的版本,在我的文件中我输入正确(即你是怎么做的)。但是,我仍然收到该错误
  • 我认为它应该适用于枚举类。如果没有看到实际来源,我无法说出它为什么不起作用。
  • #define ENUM_HAS_ASSOCIATION(T) template&lt;typename T&gt; struct Assoc; #define ENUM_ASSOCIATION(T, V) template&lt;&gt; Assoc&lt;T&gt; struct Assoc {using type = V;}; #define ENUM_TYPE(T) Assoc&lt;T&gt;::type; + ENUM_HAS_ASSOCIATION(eOmnibusOrder) ENUM_ASSOCIATION(eOmnibusOrder::RARITY, eRarity) (对不起,我不知道是否有更好的格式或回复方法我没有经常使用这个网站)
【解决方案2】:

这是元功能的教科书应用程序。由于该问题被标记为 C++,因此我会避免使用宏解决方案并采用常见做法。

让我们先检查一下解决方案:

enum Sorting { COLOR, PRICE };
enum Color { RED, BLUE };
enum Price { CHEAP, EXPENSIVE };

// auto is used for non type template parameters
template <auto any_enum_value>
struct SortCategory;

template <>
struct SortCategory<COLOR>
{
    using type = Color;
};

template <>
struct SortCategory<PRICE>
{
    using type = Price;
};

Demo

上面的代码提供了一个元函数SortCategory;这是一个可以专门用于Sorting 枚举值的结构。你基本上可以用这种方式做任何事情,上面选择了以下映射:

SortCategory<COLOR> -> Color
SortCategory<PRICE> -> Price

映射类型(枚举)是演示中所示的嵌套类型别名。

编辑:SortCategory 已更新以适应任何非类型模板参数。使用auto,您可以传递任何枚举的值,从而使您的映射超出排序枚举类型。

【讨论】:

  • 我唯一的问题是我在 Unreal 中工作,它讨厌模板(我也是,认为它们完全不如 c# 泛型)。我以前从未见过以这种方式使用“使用”。我想我仍然可以使用宏来简化创建这些嵌套类型别名的过程。有没有办法让“template”更加通用,以便它可能适用于其他枚举?
  • @DemonBismuth C# 泛型与 Java 泛型非常相似,并且依赖于类型擦除,这在运行时会产生成本。模板是纯编译时的,您可以使用模板进行类型擦除等等
  • @463035818_is_not_a_number 我仍然更喜欢能够继承泛型类型的灵活性,即使有这个成本。成本值得可用性
  • @DemonBismuth 虚幻引擎中的核心 API 的大部分是模板化的。甚至可以提前实现概念和“要求”条款。我不知道你从哪里得到虚幻引擎“讨厌”的模板,它使用 C++,就是这样。如果您因为使用的“不安”而讨厌模板,那就另当别论了。如果您更喜欢 C# 泛型,我建议 Unity 确实利用了这些东西。 C++(尤其是在游戏开发领域)就是不支付额外费用
  • Unreal 对我并不友好,我更喜欢 Unity,但我的工作是使用 Unreal。使它们与蓝图很好地交互(以便我们的艺术家可以使用它们)使得使用模板变得困难,并且关于如何制作自定义、兼容的模板代码的文档不存在或难以解析。
猜你喜欢
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-09
相关资源
最近更新 更多