I was playing around with constexpr
constructors in C++14 and above and noticed something strange. Here is my code:
#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;
}
Simple enough example. I compiled it with g++ -std=c++14 -o cx_test cx_test.cpp
, expecting it to give me a compile error (because I am using cout
and the stream operator to print the function's name. But, to my surprise, it compiled! When I ran it, it gave the following output:
$> 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()
$>
But, when I compile with clang, I get:
$> 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.
$>
This seems like a bug with g++ because the constructor appears to violate the restrictions of constexpr
, but I am not quite sure. Which compiler is correct?
Here is the g++ version and here is the clang version (on ideone).