【发布时间】:2020-12-03 22:31:18
【问题描述】:
我想知道是否可以从枚举类生成类型集以用于元编程目的。 我最初是一名 C# 程序员,习惯于使用很多属性进行反射和元编程。例如,对我来说,用 C# 编写类似的 sn-p 是一种通用模式:
public enum ComponentEnum { Component1, Component2, Component3 }
[Component(ComponentEnum.Component1)]
public class Component1
{
/* Some code */
}
public static class ComponentsMeta
{
private static Dictionary<Type, ComponentEnum> map;
static ComponentMeta() { /*process the whole codebase via reflection, search Component marked classes an fill the map */}
public static bool IsComponent<T>() => map.ContainsKey(typeof(T));
public static int GetComponentUID<T>() => (int)map[typeof(T)];
}
当然,这是一个非常基本的 sn-p,没有断言和其他一些东西,但我相信你明白了。
我想在 c++ sn-p 中做出同样的行为。我真正想做的是创建一个名为Components 的类型,它将包含一些实用函数,如bool Components::isComponent<T>() 或size_t Components::getComponentUID<T>() 或一些相关的东西。到目前为止我见过的最好的方法是自己写下来,制作一个类似的元类
template <typename Ts..>
class ComponentsData
{
/* functions impl here */
}
typedef ComponentsData<C1, C2, C3> Components;
所以,现在我可以询问Components<C1>::getComponentUID(),它会返回该组件的 uid(取决于它作为模板参数的位置或该组件的 constexpr 值,没关系)。但这是一种非常不方便的方法,我想知道我是否可以在组件类中放置一个宏或使用属性和代码生成步骤或其他东西。换句话说,我的目标是以某种方式标记它应该在该组件集中的类,并在以后使用它。为此目的,c++ 可以提供什么?
如果我能像 C# 那样做一些事情就可以了——创建一个枚举类,列出所有组件,然后在组件类中写一个 constexpr 值(或枚举类附近的某个地方,两种方式都很好为了我)。 我的意思是这样的:
/* ComponentsEnum.h */
enum class ComponentsEnum { Comp1, Comp2, Comp3 };
// Here is some magic to generate Components<C1, C2, C3> metaclass.
/* another file */
#include "ComponentsEnum.h"
struct C1 { const ComponentsEnum MyValue = ComponentsEnum::Comp1; };
或者类似的东西
/* ComponentsEnum.h */
enum class ComponentsEnum { Comp1, Comp2, Comp3 };
// Here is all the magic
// All enum members concats into `Components<Comp1, Comp2, Comp3, ...>`
ConcatAll<ComponentsEnum>();
/* another file */
#include "ComponentsEnum.h"
struct Comp1 { };
或者也许是宏魔法的东西:
/* ComponentsEnum.h */
enum class ComponentsEnum { Comp1, Comp2, Comp3 };
#define InitMeta(ComponentsEnumMember) /* Some Magic */
/* another file */
#include "ComponentsEnum.h"
struct Comp1 { InitMeta(ComponentsEnum::Comp1) };
提前致谢!
【问题讨论】:
-
不,遗憾的是,目前还没有通用的方法来获取所有已定义枚举常量的列表。反射不会早于 C++23。但是你试图做的不是一个好主意 - 为类型分配一些项目范围的 ID 违背了单独的编译机制,你将很难保持一切同步。有了足够多的全局变量和它们的静态初始化,它可能就可以完成,但不是在编译时。
-
@Quimby 好的,那么不使用枚举,而是使用另一种机制呢?代码生成,属性标记,还是什么?只是外部变量初始化?
-
我做了一个回答,因为它不适合评论。它做了 ID 的事情,但实际上,如果你想在任何严肃的项目中使用它,请先尝试找到其他东西,或者至少做足够的研究以真正理解代码中每个关键字的作用。
标签: c++ metaprogramming