具有可变成员的constexpr对象 [英] constexpr object with mutable member

查看:90
本文介绍了具有可变成员的constexpr对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想出了这堂课:

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)
}

问题:

  • 为什么GetXX+Z一起作为返回表达式可以很好地编译(Z不是constexpr).
  • 如何从constexpr对象(pt)中调用FoolConstGetY方法?
  • mainGetX的行为在编译器中有所不同. MSVC可以使用int作为模板参数进行编译,而GCC( IdeOne )不会对其进行编译.
  • Why GetX is compiling well with X+Z as return expression (Z is not constexpr).
  • How can I call FoolConst and GetY methods out of constexpr object (pt) ?
  • The behaviour of GetX in main is different in compilers. MSVC compiles fine with a int 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?

推荐答案

答案:

为什么GetXX+Y作为返回表达式可以很好地编译(Z不是constexpr).

Why GetX is compiling well with X+Y as return expression (Z is not constexpr).

  • 因为用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 declared mutable.
    • 如何从constexpr对象(pt)中调用FoolConstGetY方法? GetX在main中的行为在编译器中是不同的. MSVC可以使用int作为模板参数进行编译,而GCC(IdeOne)不会进行编译.

      How can I call FoolConst and GetY methods out of constexpr object (pt) ? The behaviour of GetX in main is different in compilers. MSVC compiles fine with a int as template argument, while GCC (IdeOne) won't compile it.

      • 它适用于我,适用于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 in GetX() because the use of mutable field destroys constexpr (OTOH the behavior of gcc is a little bit misleading because it should report the error already in the definition of GetX(): either that it must be defined or otherwise can't be constexpr, 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 a mutable 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对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆