非constexpr函数在constexpr构造函数中的使用是有效的

Nmd*_*ery 5 c++ compile-time stdvector

以下内容在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()) {}
};
Run Code Online (Sandbox Code Playgroud)

std :: vector不是为了在编译时工作而设计的,那么这个代码到底是什么类型的代码呢?我已经使用了这个类来确保它没有经过优化.

dyp*_*dyp 5

这是不正确的,但不需要诊断.问题是,对于任何模板参数f(),constexpr Value(const type_t& value): compile_time_bool(f())可能不会出现在常量表达式中.但考虑一下:

struct A{};
struct B{};

bool foo(A);
constexpr bool foo(B) { return {}; }

template<class T>
constexpr bool bar(T p) { return foo(p); }
Run Code Online (Sandbox Code Playgroud)

这里,constexprness bar取决于模板参数.因此:

constexpr A a{};
constexpr B b{};

//constexpr auto ba {bar(a)};  // error
constexpr auto ba {bar(b)};    // fine
auto ba2 {bar(a)};             // fine
Run Code Online (Sandbox Code Playgroud)

标记为constexpr可以生成constexpr和非特化的函数模板constexpr,具体取决于模板参数.

可能很难或不可能检查函数模板是否不适constexpr用于任何模板参数集(在OP的情况下,可以看到f()明确指出的那样Value::f).因此,不需要诊断.


相关段落是[dcl.constexpr]/6:

如果constexpr函数模板的实例化模板特化或类模板的成员函数无法满足constexpr函数或constexpr构造函数的要求,则该特化不是constexpr函数或constexpr构造函数.[ 注意:如果函数是成员函数,它仍然是const,如下所述.- 结束注释 ]如果没有模板的特化会产生constexpr函数或constexpr构造函数,程序就会形成错误; 无需诊断.

注意const事项将在C++ 1y中解除,因此更好的标记成员函数(显然不是ctors)同时作为constexprconst.


实际上,该计划有UB.但是一旦你在需要常量表达式的上下文中实例化ctor,你的编译器应该抱怨 - 就像clang ++ 3.4一样

如果在不需要常量表达式的上下文中使用ctor,则两个编译器似乎都接受您的程序.我会说这是一个扩展,但在这种情况下("使用扩展名,不可移植的代码")发出警告很困难,因为诊断程序首先是不正确的.