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

时间:2013-12-07 04:49:35

标签: c++ stdvector compile-time

以下内容在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不是为了在编译时工作而设计的,那么这个代码到底是什么类型的代码呢?我已经使用了这个类来确保它没有经过优化。

1 个答案:

答案 0 :(得分: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); }

此处,constexpr的{​​{1}}取决于模板参数。因此:

bar

标记为constexpr A a{}; constexpr B b{}; //constexpr auto ba {bar(a)}; // error constexpr auto ba {bar(b)}; // fine auto ba2 {bar(a)}; // fine 的功能模板可以生成constexpr和非constexpr专精,具体取决于模板参数。

对于任何一组模板参数,可能很难或无法检查函数模板是否不是constexpr(在OP的情况下,可能会看到constexpr明确指出f())。因此,无需诊断。


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

  

如果Value::f函数模板的实例化模板特化或类模板的成员函数无法满足constexpr函数或constexpr构造函数的要求,则该特化不是constexpr函数或constexpr构造函数。 [注意:如果函数是成员函数,它仍然是const,如下所述。 - 结束注释]如果模板没有专门化的话   产生一个constexpr函数或constexpr构造函数,该程序是不正确的;无需诊断。

N.B。 constexpr事件将在C ++ 1y中解除,因此更好的标记成员函数(显然不是ctors)同时作为constconstexpr


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

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