英文:
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 <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; // see the comma!
for(int i = 0; i < x; ++i) {
printf("Hello world!");
}
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: '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__
| ^~~~~~~~~~~
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)) // => CAT (1,2)
CAT (1,2) // => 12
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论