【发布时间】:2015-08-10 19:00:39
【问题描述】:
我有几个宏,一个返回一个值,另一个返回 void 函数 case,基本上用它的参数和 (void)0 调用另一个。在使用 VS 和 GCC 进行编译时,在构造函数中调用它的情况下,我遇到了一些意想不到的编译问题。
我尝试运行以下命令,在 ubuntu 14.04 上使用 gcc b.cpp(gcc 版本 4.8.4)、clang c.bpp(clang 版本 3.4-1)和 win7 上的一些 VS2013 取消注释 5 个案例中的每一个,
#include <cstdio>
struct A {
A() {
return ((void)0); // case 0 => gcc err, clang ok, msvc err
//return (void)0; // case 1 => gcc err, clang ok, msvc ok
//return (); // case 2 => gcc err, clang err, msvc err
//return; // case 3 => gcc ok, clang ok, msvc ok
//; // case 4 => gcc ok, clang ok, msvc ok
}
} a;
int main()
{
printf("%p\n", &a);
}
我希望所有人都会产生类似的效果(好吧,我不确定情况 2),但我却遇到了一些奇怪的失败......
案例2:
$ gcc b.cpp
b.cpp: In constructor ‘A::A()’:
b.cpp:7:17: error: expected primary-expression before ‘)’ token
return ();
^
b.cpp:7:17: error: returning a value from a constructor
$ clang b.cpp
b.cpp:7:17: error: expected expression
return ();
^
1 error generated.
案例一:
$ gcc b.cpp
b.cpp: In constructor ‘A::A()’:
b.cpp:6:22: error: returning a value from a constructor
return (void)0;
案例 0:
$ gcc b.cpp
b.cpp: In constructor ‘A::A()’:
b.cpp:5:24: error: returning a value from a constructor
return ((void)0);
这里的正确行为是什么?我该如何调整说几个宏,比如
#define MOO(a, b, retVal) \
do \
... \
return (retVal); \
while(0)
#define FOO(a, b) MOO((a), (b), (void)0)
也为 c'tors 工作?是否有更 c++ 的方式来使用 decltype 返回 (void)0、-1、SOME_NONE 和其他默认值,以便在此类宏中中止错误处理?
(一个有点不相关的问题是,gcc 大约在代码中的什么位置决定我从 c'tor 返回一个值?)
【问题讨论】:
-
为此使用宏的想法很愚蠢。重新考虑您的设计,改用模板化的内联函数!
-
虽然这个想法很好,但对于我来说这并不是一个真正的选择,因为它需要能够从当前函数返回。
-
除非你建议我手动操作堆栈?这也不是一个选择,TBH
-
如果通过 void 函数调用返回可以在构造函数中工作会很有趣,因为从下面的答案中构造函数不应该使用带有值的
return,而void明确声明 没有价值. -
是的,这就是我的意思,规范说“从函数的末尾流出等同于没有值的返回;这会导致返回值的函数出现未定义的行为。”我认为这同样适用于c'tor。但另一方面,
(void)0也是无价值的,所以我认为它是等价的。
标签: c++ gcc language-lawyer return-type clang++