允许在宏内使用初始化程序列表

问题描述 投票:0回答:2

[我正在研究的项目中有一个记录表达式的宏。我的任务是添加以下功能:将多个值传递到其中,并单独打印每个图像。我设法通过1到5个参数使此工作相对容易。仍然可以很好地传递到函数中。

我现在遇到的问题是初始化程序列表不再起作用。该项目使用可变参数作为内部数组的初始化对象,例如func(std::vector<int>{0, 1, 0, 1})。自从我实现了multi arg之后,由于逗号的原因,它不再起作用。

我知道我可以执行func((std::vector<int>{0, 1, 0, 1})),这会很好,但是我知道这不会因工作而受到欢迎。有没有一种方法可以使我的产品在没有多余括号的情况下工作,或者在需要时添加额外的括号?

以下是一些相关片段:


// Intermediate macro "chooser"
#define func_x(x, A, B, C, D, E, Func, ...) Func

// Macro to be called and used by user
// First param must be blank to allow for 0 argument function
#define func(...) func_x(, ##__VA_ARGS__, \
  func_5(__VA_ARGS__), func_4(__VA_ARGS__), func_3(__VA_ARGS__), \
  func_2(__VA_ARGS__), func_1(__VA_ARGS__), func_0())

// Macros for 1 through 5 args, calls the func_VA macro.
#define func_1(A1) func_VA(A1)
#define func_2(A1, A2) func_1(A1), func_VA(A2)
#define func_3(A1, A2, A3) func_2(A1, A2), func_VA(A3)
#define func_4(A1, A2, A3, A4) func_3(A1, A2, A3), func_VA(A4)
#define func_5(A1, A2, A3, A4, A5) func_4(A1, A2, A3, A4), func_VA(A5)

// Prints expression and type
// We use a variadic macro to support commas inside expressions (e.g.
// initializer lists):
#define func_VA(...)                                                  \
  func_macro::DebugOutput(__FILE__, __LINE__, __func__, #__VA_ARGS__) \
      .print(func_macro::type_name<decltype(__VA_ARGS__)>(), (__VA_ARGS__))

func(std::vector<int>{0, 1, 0, 1});
// Errors

func((std::vector<int>{0, 1, 0, 1}));
// Works, but also prints the () when logging so not ideal. Better than nothing though.

我一直在尝试在宏的某些部分加上方括号,以尝试解决此问题,但无济于事。像#define func_1(A1) func_VA((A1))或类似名称。

编辑:我已经取得了一些进展

您可以假设,如果我叫func_1,则像#define func_1(...) func_VA(__VA_ARGS__)一样声明func_1(std::vector<int>{0, 1, 0, 1});也可以。

我制作了一个返回(__VA_ARGS__)的“包装器”宏,尽管该字符串版本确实带有多余的括号,但它允许该宏与列表init一起正常使用。尽管我无法通过某种方式使您(作为用户)不必在数组上调用包装器(这比将braccets放置在自己的位置上更难)。

c++ preprocessor
2个回答
0
投票

如果可以将DebugOutput::print更改为可变参数模板,则可以执行以下操作:

#define func(...)                                                     \
  func_macro::DebugOutput{__FILE__, __LINE__, __func__, #__VA_ARGS__} \
      .print(__VA_ARGS__)


namespace func_macro
{

struct DebugOutput
{
    const char* filename = nullptr;
    int line = 0;
    const char* funcname = nullptr;
    const char* argsString = nullptr;

    template <typename ... Ts>
    void print(const Ts&... args) const
    {
        std::cout << filename << ":" << line << " in " << funcname << std::endl;
        std::cout << "func(" << argsString << ")\n";

        ((std::cout << typeid(args).name() << ": " << args << std::endl), ...);
    }
};

}

Demo

© www.soinside.com 2019 - 2024. All rights reserved.