【发布时间】:2018-08-02 20:41:31
【问题描述】:
我在使用 C++14 及更高版本的 constexpr 构造函数时发现了一些奇怪的东西。这是我的代码:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
#define PFN(x) cout << x << __PRETTY_FUNCTION__ << endl
#define PF PFN("")
#define NL cout << endl
struct A {
constexpr A() { PF; }
virtual ~A() { PF; NL; }
};
struct B : A {
constexpr B() { PFN(" "); }
virtual ~B() { PFN(" "); }
};
int main(int argc, char** argv) {
{ A a; }
{ B b; }
A* a = new B;
delete a;
return 0;
}
足够简单的例子。我用g++ -std=c++14 -o cx_test cx_test.cpp 编译它,期望它给我一个编译错误(因为我使用cout 和流运算符来打印函数的名称。但是,令我惊讶的是,它编译了!当我运行它时,它给出了以下输出:
$> g++ -std=c++14 -o cx_test cx_test.cpp && ./cx_test
constexpr A::A()
virtual A::~A()
constexpr A::A()
constexpr B::B()
virtual B::~B()
virtual A::~A()
constexpr A::A()
constexpr B::B()
virtual B::~B()
virtual A::~A()
$>
但是,当我用 clang 编译时,我得到:
$> clang++ -std=c++14 -o cx_test cx_test.cpp && ./cx_test
cx_test.cpp:12:15: error: constexpr constructor never produces a constant expression [-Winvalid-constexpr]
constexpr A() { PF; }
^
cx_test.cpp:12:21: note: non-constexpr function 'operator<<<std::char_traits<char> >' cannot be used in a constant expression
constexpr A() { PF; }
^
cx_test.cpp:9:12: note: expanded from macro 'PF'
#define PF PFN("")
^
cx_test.cpp:8:26: note: expanded from macro 'PFN'
#define PFN(x) cout << x << __PRETTY_FUNCTION__ << endl
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/ostream:556:5: note: declared here
operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
^
1 error generated.
$>
这似乎是 g++ 的一个错误,因为构造函数似乎违反了constexpr 的限制,但我不太确定。哪个编译器是正确的?
【问题讨论】:
-
可能与this one 相关,您是否尝试过
-fno-builtin...operator <<不是constexpr,但它可能会被折叠成内置函数。 -
-fno-builtin不会影响任何一个。关于另一个问题,我不确定 c++14 和 c++17 中对constexpr的宽松要求是否会影响接受的答案。 -
它们都是正确的......我上面链接的答案解释了为什么这是不正确的不需要诊断......你不会强迫它们在常量表达式上下文中使用see modified version where gcc generates an error当你强制它在常量表达式上下文中使用时。
-
如果您想要 C++14 特定的引用,请参阅 this question,它涵盖了类似的基础并提供了 C++14 的相同细节。
标签: c++ gcc clang c++14 constexpr