【问题标题】:Getting too many arguments provided to function-like macro invocation compile error while defining lambda inside assert (assert.h) in Xcode [c++]在 Xcode [c++] 中的 assert (assert.h) 中定义 lambda 时,为类似函数的宏调用提供了太多参数编译错误
【发布时间】:2016-06-27 17:02:09
【问题描述】:

我正在使用 assert.h 中的断言宏 我已经定义了 lambda 来执行断言检查。

int val1 = 0;
int val2 = 1;

const auto check = [val1,val2]()-> bool
{
    return val1 < val2;
};
// no error for this call
assert(check() && "Test is failed");

// no error for this call
assert([=]()-> bool
       {
           return val1 < val2;
       }() && "Test is failed");
//compile error for this call "too many arguments provided to function-like macro invocation"
assert([val1,val2]()-> bool
       {
           return val1 < val2;
       }() && "Test is failed");

我为什么会得到

提供给类函数宏调用的参数过多

当我使用断言宏并在捕获列表中定义具有多个参数的 lambda 时编译错误?

【问题讨论】:

    标签: c++ xcode c++11 lambda macros


    【解决方案1】:

    问题是捕获列表中的逗号。

    预处理器对 C++ 语法的理解极其有限,它主要进行琐碎的文本替换。如果逗号不在匹配的内括号之间(当然也不是像字符串文字那样的标记的一部分),预处理器会将其视为宏调用的参数分隔符。

    因此预处理器认为您正在调用带有两个参数 [this 的断言以及第一个逗号后面的其余内容,这会产生错误。

    您可以通过使用一组额外的括号来修复此错误:

    int i = -7, j = 7;
    assert(([i,j](){return i + j;}()));
    

    对于标准爱好者:

    由最外面的匹配括号包围的预处理标记序列形成了 类函数宏的参数。 列表中的各个参数用逗号分隔 预处理标记,但匹配的内括号之间的逗号预处理标记不分开 参数。 如果参数列表中有预处理标记序列,否则 充当预处理指令,155 行为未定义。

    N4140 中的 16.3/11,强调我的。

    【讨论】:

    • Baum mit Augen 还有一点不清楚,assert.h 中 assert 的参数在 () #define assert(e) \ (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0)
    • @TM 这些括号来得太晚了,对于上面的引用,括号和逗号之前扩展是相关的,而不是结果中的那些。
    【解决方案2】:

    预处理器非常简单,它将所有逗号视为参数分隔符。

    因此,如果您将带有逗号的任何内容作为参数传递给宏,则不能使用宏。

    【讨论】:

    • Joachim Pileborg 为什么在使用 [=] 调用时不会为其他逗号抛出编译错误?
    • @TM 老实说,我不认为你在告诉我们真相。预处理器没有实际 C++ 代码或 C++ 语法的概念或知识,预处理器只知道它自己的有限语言,其中宏“调用”中的所有逗号都用作参数分隔符。因此,我不相信代码会起作用并且不会给您错误。
    • Joachim Pileborg 但它可以工作:) 没有任何编译错误我使用的是 Xcode 版本 7.2.1 (7C1002)
    • 这很奇怪,在 GCC 5.2.1 中也适用于我。但它不应该起作用。问题似乎是捕获列表中的逗号。我将不得不检查标准,看看他们是否对 C++11 进行了任何更改以使预处理器更加智能。
    • “列表中的各个参数由逗号预处理标记分​​隔,但匹配的内括号之间的逗号预处理标记不分隔参数。” N4140 中的 16.3/11。所以 gcc 似乎是正确的。在 C++XX 之前不是这样吗?如果是这样,为了什么 XX?
    猜你喜欢
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 1970-01-01
    • 2021-01-17
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多