以下内容在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不是为了在编译时工作而设计的,那么这个代码到底是什么类型的代码呢?我已经使用了这个类来确保它没有经过优化。
答案 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)同时作为const
和constexpr
。
实际上,该计划有UB。但是一旦你在需要常量表达的上下文中实例化ctor,你的编译器应该抱怨 - 就像clang ++ 3.4一样
如果在不需要常量表达式的上下文中使用ctor,两个编译器似乎都接受您的程序。我会说这是一个扩展,但在这种情况下(“使用扩展名,不可移植的代码”)发出警告很困难,因为诊断程序首先是不正确的。