我想使用宏或模板元编程为我生成一些代码。

huangapple go评论59阅读模式
英文:

I want to use macros or template metaprogramming to generate some code for me

问题

Sure, here's the translated code part:

我需要定义一个枚举,类似于

enum class MyEnum { MyEnum1 = 0x0001, MyEnum2 = 0x0002, MyEnum3 = 0x0004, MyEnum4 = 0x0008, MyEnum5 = 0x0010 };

所以基本上这些枚举值是1左移枚举索引,我希望在将来某人添加新的枚举值时避免任何拼写错误,我可以简单地为命名枚举定义一个字符串数组并生成相应的函数,根据枚举的索引返回值。

这可以分解成以下内容。假设我有一个数组

constexpr std::array<const char*, 3> arr = {"Foo", "Bar", "Baz"};

//现在在编译时我想生成函数
constexpr int getFoo() { return 0; }
constexpr int getBar() { return 1; }
constexpr int getBaz() { return 2; }

基本上,我想遍历数组并生成数组中值的getter函数,然后返回数组中的索引。

不确定是否可能,但我模糊记得可以使用宏中的 ## 生成这样的代码。



<details>
<summary>英文:</summary>

I need to define an enum like 
enum class MyEnum { MyEnum1 = 0x0001, MyEnum2 = 0x0002, MyEnum3 = 0x0004, MyEnum4 = 0x0008, MyEnum5 = 0x0010 };
 So basically these enum values are 1 shifted by the index of enum I want to avoid any typos in case in future some adds a new enum value and I can simply define an array of string for the named enums and generate functions for it and return value based on the index of enum.

this can be broken down to something like this . Say I have an array 
constexpr std::array&lt;const char*, 3&gt; arr = {&quot;Foo&quot;, &quot;Bar&quot;, &quot;Baz&quot;};

//Now at compile time i want to generate functions 
constexpr int getFoo() { return 0; }
constexpr int getBar() { return 1; }
constexpr int getBaz() { return 2; }
Basically i want to iterate over array and generate getter functions over the values in array and return the index in array. 

Not sure even if its possible but vaguely remember such code being generated using ## in macros

</details>


# 答案1
**得分**: 3

> 我需要定义一个枚举,类似这样的枚举类:enum class MyEnum { MyEnum1 = 0x0001, MyEnum2 = 0x0002, MyEnum3 = 0x0004, MyEnum4 = 0x0008, MyEnum5 = 0x0010 };

请查看 [`macro_sequence_for`](https://github.com/HolyBlackCat/macro_sequence_for)。这几乎与自述文件中的第一个示例几乎完全相符。

&lt;kbd&gt;[在 gcc.godbolt.org 上运行][1]&lt;/kbd&gt;
```cpp
#include &quot;macro_sequence_for.h&quot;

#define MAKE_FLAGS(name, seq) enum name {SF_FOR_EACH(BODY, STEP, FINAL, 0, seq)};
#define BODY(n, d, x) x = 1 &lt;&lt; (d),
#define STEP(n, d, x) d+1
#define FINAL(n, d) _mask = (1 &lt;&lt; (d)) - 1

MAKE_FLAGS(E, (a)(b)(c))

这会扩展为:

enum E
{
    a = 1 &lt;&lt; (0),                // 0b0001
    b = 1 &lt;&lt; (0+1),              // 0b0010
    c = 1 &lt;&lt; (0+1+1),            // 0b0100
    _mask = (1 &lt;&lt; (0+1+1+1)) - 1 // 0b0111
};

如果您不需要组合的掩码,可以删除 #define FINAL 并在其位置传递 SF_NULL

完整披露 - 我是该库的作者。

英文:

> I need to define an enum like enum class MyEnum { MyEnum1 = 0x0001, MyEnum2 = 0x0002, MyEnum3 = 0x0004, MyEnum4 = 0x0008, MyEnum5 = 0x0010 };

Take a look at macro_sequence_for. This almost exactly matches the very first example in the readme.

<kbd>run on gcc.godbolt.org</kbd>

#include &quot;macro_sequence_for.h&quot;

#define MAKE_FLAGS(name, seq) enum name {SF_FOR_EACH(BODY, STEP, FINAL, 0, seq)};
#define BODY(n, d, x) x = 1 &lt;&lt; (d),
#define STEP(n, d, x) d+1
#define FINAL(n, d) _mask = (1 &lt;&lt; (d)) - 1

MAKE_FLAGS(E, (a)(b)(c))

This expands to:

enum E
{
    a = 1 &lt;&lt; (0),                // 0b0001
    b = 1 &lt;&lt; (0+1),              // 0b0010
    c = 1 &lt;&lt; (0+1+1),            // 0b0100
    _mask = (1 &lt;&lt; (0+1+1+1)) - 1 // 0b0111
};

If you don't need the combined mask, remove #define FINAL and pass SF_NULL in its place.

Full disclosure - I'm the library author.

huangapple
  • 本文由 发表于 2023年4月11日 02:34:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75979728.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定