【问题标题】:Variable arguments macro and parameter pack expansion变量参数宏和参数包扩展
【发布时间】:2019-02-23 17:34:27
【问题描述】:

在下面的示例代码中,我想使用带有可变参数的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;
}

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:
    1. 可变参数模板不能自动为std::initializer_list。所以让我们用大括号包裹可变参数。
    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 测试过。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-29
      • 2020-03-31
      • 1970-01-01
      • 1970-01-01
      • 2015-05-21
      • 1970-01-01
      相关资源
      最近更新 更多