Question

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.

Était-ce utile?

La 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 constexprness 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top