The following is valid in gcc 4.8:
class Value {
private:
static std::vector<float> compile_time_vector;
const bool compile_time_bool;
static bool f(void) {
compile_time_vector.push_back(2.3);
return true;
}
public:
template <typename type_t>
constexpr Value(const type_t& value): compile_time_bool(f()) {}
};
std::vector isn't designed to work at compile time, so exactly what kind of code is this generating? I've used the class to make sure it isn't optimized out.
This is ill-formed, but no diagnostic is required. The problem is that f()
in constexpr Value(const type_t& value): compile_time_bool(f())
may not appear in a constant expression for any template argument. But consider:
struct A{};
struct B{};
bool foo(A);
constexpr bool foo(B) { return {}; }
template<class T>
constexpr bool bar(T p) { return foo(p); }
Here, the constexpr
ness of bar
depends on the template argument. Therefore:
constexpr A a{};
constexpr B b{};
//constexpr auto ba {bar(a)}; // error
constexpr auto ba {bar(b)}; // fine
auto ba2 {bar(a)}; // fine
A function template marked as constexpr
can produce constexpr
and non-constexpr
specializations, depending on the template arguments.
It is probably hard or impossible to check if a function template is not constexpr
for any set of template arguments (in the OP's case, it could be possible to see that as f()
unambiguously refers to Value::f
). Therefore, no diagnostic is required.
The relevant paragraph is [dcl.constexpr]/6:
If the instantiated template specialization of a
constexpr
function template or member function of a class template would fail to satisfy the requirements for aconstexpr
function orconstexpr
constructor, that specialization is not aconstexpr
function orconstexpr
constructor. [Note: If the function is a member function it will still be const as described below. — end note ] If no specialization of the template would yield aconstexpr
function orconstexpr
constructor, the program is ill-formed; no diagnostic required.
N.B. the const
thing will be lifted in C++1y, so better mark member functions (not ctors, obviously) both as both constexpr
and const
.
Effectively, the program has UB. But once you instantiate the ctor in a context that requires a constant expression, your compiler should complain -- as does clang++3.4
Both compilers seem to accept your program if you use the ctor in a context where a constant expression is not required. I'd say that's an extension, but it's as hard to issue a warning in this case ("extension used, nonportable code") as to diagnose the program is ill-formed in the first place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With