有没有任何C++代码无法通过身份预处理宏传递?

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

Is there any C++ code that can't be passed through an identity preprocessor macro?

问题

给定:

```c++
#define IDENTITY(...) __VA_ARGS__

在将代码包装在此宏调用中时,是否存在编译器会拒绝但通常会接受的代码?更简单的 #define IDENTITY(x) x 如果有逗号就会失败,但上面的代码似乎相当稳健,GCC 会高兴地接受这个:

#include <stdio.h>;

#define IDENTITY(...) __VA_ARGS__

IDENTITY(
    struct does_this_work {
        float yes;
        double appears_to;
    };

    template<class T> int what_about_this() {
        int x = 50, y = 0; // 看到逗号了吗!
        for(int i = 0; i < x; ++i) {
            printf("Hello world!");
        }
        return 3;
    }
)

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

Given:

```c++
#define IDENTITY(...) __VA_ARGS__

Is there any code that the compiler will reject, that it would normally accept, when wrapped in an invocation of this macro? The simpler #define IDENTITY(x) x will fail if there are any commas but the above seems pretty robust, GCC happily accepts this:

#include &lt;stdio.h&gt;

#define IDENTITY(...) __VA_ARGS__

IDENTITY(
    struct does_this_work {
        float yes;
        double appears_to;
    };

    template&lt;class T&gt; int what_about_this() {
        int x = 50, y = 0; // see the comma!
        for(int i = 0; i &lt; x; ++i) {
            printf(&quot;Hello world!&quot;);
        }
        return 3;
    }
)

答案1

得分: 3

在我的经验中,混淆预处理器,或者利用预处理器来混淆后续编译阶段,总是一种打破“健壮”宏的可行策略。

我使用MingW32(带有gcc 10.3.0)。以下代码编译没有错误:

#define FOO
FOO
#undef FOO
#define FOO2 int x();
FOO2;

但是下面的代码会导致编译器报错(使用命令行 g++ -c test.cpp):

#define IDENTITY(...) __VA_ARGS__

IDENTITY(
#define FOO
FOO
#undef FOO
#define FOO2 int x()
FOO2;
)

编译器会发出严重的投诉:

test.cpp:7:5: error: 'FOO' does not name a type; did you mean 'FOO2'?
    7 |     FOO
      |     ^~~
test.cpp:1:23: note: in definition of macro 'IDENTITY'
    1 | #define IDENTITY(...) __VA_ARGS__
      |                       ^~~~~~~~~~~

我没有尝试解释为什么会发生这种情况。

[我估计现在问题可能会更改,要求不在宏的参数中使用预处理器]。

英文:

In my experience, confusing the preprocessor, or using the preprocessor to confuse later phases of compilation, is always a viable strategy for breaking "robust" macros.

I have MingW32 (with gcc 10.3.0). The following code compiles without error

#define FOO
FOO
#undef FOO
#define FOO2 int x();
FOO2;

but

#define IDENTITY(...) __VA_ARGS__

IDENTITY(
#define FOO
FOO
#undef FOO
#define FOO2 int x()
FOO2;
)

gets the compiler complaining bitterly (with command line g++ -c test.cpp).

test.cpp:7:5: error: &#39;FOO&#39; does not name a type; did you mean &#39;FOO2&#39;?
    7 |     FOO
      |     ^~~
test.cpp:1:23: note: in definition of macro &#39;IDENTITY&#39;
    1 | #define IDENTITY(...) __VA_ARGS__
      |                       ^~~~~~~~~~~

I haven't tried to pick apart why this happens.

[I estimate a non-zero likelihood that the question will now change to require no use of the processor in the argument of the macro].

答案2

得分: 3

#define IDENTITY(...) VA_ARGS
#define CAT(X,Y) X##Y

IDENTITY(CAT) IDENTITY((1,2)) // => CAT (1,2)

CAT (1,2) // => 12

英文:
#define IDENTITY(...) __VA_ARGS__
#define CAT(X,Y) X##Y

IDENTITY(CAT) IDENTITY((1,2))  // =&gt; CAT (1,2)

CAT (1,2) // =&gt; 12

huangapple
  • 本文由 发表于 2023年6月15日 11:30:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76478903.html
匿名

发表评论

匿名网友

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

确定