具有可变成员的constexpr对象 [英] constexpr object with mutable member
问题描述
我想出了这堂课:
class Point
{
public:
int X, Y;
mutable int Z;
constexpr Point(int x, int y) :X (x), Y(y), Z(0)
{ }
constexpr int GetX() const
{
// Z++; // Wont compile, but following expression is valid!
return X+Z;
}
int GetY() const
{
Z++;
return Y;
}
void FoolConst() const
{
Z++;
}
};
这是用法:
template<int S>
void foo()
{
std::cout << S << std::endl;
}
int main()
{
constexpr Point pt(10, 20);
pt.FoolConst();
char arr[pt.GetX()]; // Both compile, but GCC is using extended `new`
foo<pt.GetX()>(); // GCC fails, VC compiles
std::cout << sizeof(arr); // 10 (MSVC), 11 (GCC)
std::cout << pt.GetX(); // 11 (MSVC), 11(GCC)
}
问题:
- 为什么
GetX
与X+Z
一起作为返回表达式可以很好地编译(Z不是constexpr). - 如何从
constexpr
对象(pt
)中调用FoolConst
和GetY
方法? -
main
中GetX
的行为在编译器中有所不同. MSVC可以使用int
作为模板参数进行编译,而GCC( IdeOne )不会对其进行编译.
- Why
GetX
is compiling well withX+Z
as return expression (Z is not constexpr). - How can I call
FoolConst
andGetY
methods out ofconstexpr
object (pt
) ? - The behaviour of
GetX
inmain
is different in compilers. MSVC compiles fine with aint
as template argument, while GCC (IdeOne) won't compile it.
对于一个编译器constexpr GetX
确实是constexpr
,但是对于其他编译器而言,如果包含X+Z
则不是.如果我删除+Z
而仅仅return X
GCC可以.
For one compiler constexpr GetX
is truly constexpr
, but for other it is not if X+Z
is involved. If I remove +Z
and simply return X
GCC is okay.
我的问题很基本:如果对象是constexpr
,它如何调用非constexpr方法?
My question is very basic: If object is constexpr
how can it call a non-constexpr method?
推荐答案
答案:
为什么
GetX
用X+Y
作为返回表达式可以很好地编译(Z
不是constexpr
).
Why
GetX
is compiling well withX+Y
as return expression (Z
is notconstexpr
).
- 因为用
constexpr
声明后,整个对象是常量.对象的恒定性始终由所有成员派生,除非成员声明为mutable
. - Because whole object is constant after having been declared with
constexpr
. Const-ness of the object is always derived by all members, except when the member is declaredmutable
. - 它适用于我,适用于gcc 4.8.3.一切都很好,只要您不在
GetX()
中使用Z
,因为使用mutable
字段会破坏constexpr
(OTOH gcc的行为有点误导,因为它应该报告已经存在的错误GetX()
的定义:必须定义,否则不能为constexpr
,或者在定义时不能使用在类外部定义的可变字段或变量. - 如果您有一个编译器可以很好地编译,则将
GetX()
的结果作为模板参数传递给它,它引用一个mutable
字段,则它肯定会违反标准,并且此行为实际上是未定义的,因为它应该产生相同的结果(由于它是在编译时解决的事实),无论Z的运行时值发生了什么. - It works for me, with gcc 4.8.3. Everything is fine, as long as you don't use
Z
inGetX()
because the use ofmutable
field destroysconstexpr
(OTOH the behavior of gcc is a little bit misleading because it should report the error already in the definition ofGetX()
: either that it must be defined or otherwise can't beconstexpr
, or when defined it cannot use mutable fields or variables defined outside the class). - If you have a compiler that compiles fine passing the result of
GetX()
as template argument, which refers to amutable
field, it surely breaks the standard and this behavior is actually undefined because it should produce the same result (due to the fact that it's resolved in compile time) no matter what happened to the runtime value of Z.
如何从
constexpr
对象(pt
)中调用FoolConst
和GetY
方法?GetX
在main中的行为在编译器中是不同的. MSVC可以使用int作为模板参数进行编译,而GCC(IdeOne)不会进行编译.
How can I call
FoolConst
andGetY
methods out ofconstexpr
object (pt
) ? The behaviour ofGetX
in main is different in compilers. MSVC compiles fine with a int as template argument, while GCC (IdeOne) won't compile it.
这篇关于具有可变成员的constexpr对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!