这是有效的代码:
struct S {
constexpr S(int x, int y): xVal(x), yVal(y) {}
constexpr S(int x): xVal(x) {}
constexpr S() {}
const int xVal { 0 };
const int yVal { 0 };
};
但在这里,我真的想声明xVal
和yVal
constexpr
--如下所示:
struct S {
constexpr S(int x, int y): xVal(x), yVal(y) {}
constexpr S(int x): xVal(x) {}
constexpr S() {}
constexpr int xVal { 0 }; // error!
constexpr int yVal { 0 }; // error!
};
如上所述,代码不会编译。原因是(根据7.1.5/1),只有静态数据成员可以声明为constexpr
。但是为什么呢?
发布于 2014-12-11 03:12:45
想一想constexpr
是什么意思。这意味着我可以在编译时解析这个值。
因此,类的成员变量本身不能是xVal
所属的constexpr
...the实例,直到实例化时才存在!拥有xVal
的可能是constexp
,这将使xVal
成为constexpr
,但xVal
本身永远不可能成为constexpr
。
这并不意味着这些值不能是常量expression...in事实,类的常量表达式实例可以将变量用作常量表达式:
struct S {
constexpr S(int x, int y): xVal(x), yVal(y) {}
constexpr S(int x): xVal(x) {}
constexpr S() {}
int xVal { 0 };
int yVal { 0 };
};
constexpr S s;
template <int f>//requires a constexpr
int foo() {return f;}
int main()
{
cout << "Hello World" << foo<s.xVal>( )<< endl;
return 0;
}
编辑:下面有很多讨论,回顾了这里有几个隐含的问题。
“为什么我不能通过将类的成员声明为常量表达式来强制类的所有实例都为常量表达式?”
下面是一个例子:
//a.h
struct S;
struct A {std::unique_ptr<S> x; void Foo(); A();/*assume A() tries to instantiate an x*/}
//main.cpp
int main(int argc, char** argv) {
A a;
a->foo();
}
//S.h
struct S {
constexpr S(int x, int y): xVal(x), yVal(y) {}
constexpr S(int x): xVal(x) {}
constexpr S() {}
constexpr int xVal { 0 }; // error!
constexpr int yVal { 0 };
};
A和S的定义可能在完全不同的编译单元中,因此S必须是常量link的事实可能要等到链接时才能知道,特别是如果忘记了A的实现。这种模棱两可的情况很难调试,也很难实现。更糟糕的是,S的接口可能会完全暴露在共享库中,COM接口,ect...This可能会完全改变共享库的所有基础设施,这可能是不可接受的。
另一个原因是这是多么具有传染性。如果一个类的任何成员都是常量表达式,那么所有成员(及其所有成员)和所有实例都必须是常量表达式。以以下场景为例:
//S.h
struct S {
constexpr S(int x, int y): xVal(x), yVal(y) {}
constexpr S(int x): xVal(x) {}
constexpr S() {}
constexpr int xVal { 0 }; // error!
int yVal { 0 };
};
S的任何实例都必须是constexpr
,才能持有独占的constexpr
xval
。yVal
天生就变成了constexpr
,因为xVal
就是。没有编译器的技术原因,你不能这样做(我不认为),但它感觉不是很像C++。
“好吧,但我真的想让一个类的所有实例常量表达式。什么是技术限制,使我无法做到这一点”。
也许只有标准委员会认为这不是一个好主意。就我个人而言,我发现它的实用性很小……我真的不想定义人们如何使用我的类,只是定义当他们使用它时,我的类是如何行为的。当他们使用它时,他们可以将特定的实例声明为常量表达式(如上所述)。如果我有一些代码块,我想要一个constexpr实例,我会用一个模板来完成:
template <S s>
function int bar(){return s.xVal;}
int main()
{
cout << "Hello World" << foo<bar<s>()>( )<< endl;
return 0;
}
不过,我认为你最好使用一个常量表达式函数,它可以在限制性和非限制性两种方式下使用?
constexpr int bar(S s) { return s.xVal; }
https://stackoverflow.com/questions/27408819
复制相似问题