可变参数宏和参数包扩展

Variable arguments macro and parameter pack expansion

本文关键字:参数 扩展 变参 包扩展      更新时间:2023-10-16

在以下示例代码中,我想将带有变量参数的MACRO_EXPANSION{...}使用EnumTypes对象列表。但是,我无法使这个想法起作用。(ps。代码结构看起来不太好,但我需要它:)

#include <iostream>
#include <utility>
#include <initializer_list>
enum class EnumOneTypes {
  One0,
  One1
};
enum class EnumTwoTypes {
  Two0,
  Two1
};
struct EnumTypes {
  EnumOneTypes one;
  EnumTwoTypes two;
};
void do_something(std::initializer_list<EnumTypes> il) {
    std::cout << "Do something" << std::endl;
}
// Need this struct to forward arguments
struct Register {
  template <typename... TArgs>
  Register(TArgs&&... args) {
    do_something(std::forward<TArgs>(args)...);
    //also do other things after do_something, omit here
    // ...
  }
};
// Use this macro to define global static objects
#define MACRO_EXPANSION(name, ...) 
  static struct Register name(__VA_ARGS__)
MACRO_EXPANSION(
  register_two,
  {EnumOneTypes::One0, EnumTwoTypes::Two0},
  {EnumOneTypes::One1, EnumTwoTypes::Two1}
);
MACRO_EXPANSION(
  register_three,
  {EnumOneTypes::One0, EnumTwoTypes::Two0},
  {EnumOneTypes::One1, EnumTwoTypes::Two1},
  {EnumOneTypes::One0, EnumTwoTypes::Two1}
);
int main() {
  std::cout << "Test the usage of this macro" << std::endl;
  return 0;
}
  1. variadic模板不能自动为 std::initializer_list。因此,让我们用牙套包裹variadic参数。
struct Register {
  template <typename... TArgs>
  Register(TArgs&&... args) {
    do_something({std::forward<TArgs>(args)...}); // Make params to be initializer List
    //also do other things after do_something, omit here
    // ...
  }
};
  1. 由于Register构造函数已被模板,因此编译器似乎无法推断出哪种{EnumOneTypes::One0, EnumTwoTypes::Two0}类型。因此,让我们指定其类型:
MACRO_EXPANSION(
  register_two,
  EnumTypes{EnumOneTypes::One0, EnumTwoTypes::Two0},
  EnumTypes{EnumOneTypes::One1, EnumTwoTypes::Two1}
);

应用这两个后,它将成功编译并以输出运行:

Do something
Do something
Test the usage of this macro

我在Godbolt中进行了测试。