Non-constexpr function's use in constexpr constructor is valid

c++, compile-time, stdvector

Solution

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 a `constexpr` function or `constexpr` constructor, that specialization is not a `constexpr` function or `constexpr` 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 a `constexpr` function or `constexpr` 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.

Problem

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.

Original source