constexpr成员变量,嵌套类的问题

时间:2016-11-18 23:33:28

标签: c++ c++11

我正在尝试编写一个具有多个静态constexpr值的类;这似乎是不允许的,因为constexpr声明需要类声明中不可用的类的定义。我的第一次尝试的MCV看起来像这样:

struct A {
    constexpr A(float x) : _x(x) {}
    float _x;

    static constexpr A y = A(1.f);
    // gcc-5.1:
    // error: invalid use of incomplete type 'struct A'
    // static constexpr A y = A(1.f);
    //                             ^
    // msvc-14:
    // error C2027: use of undefined type 'A'
    // note: see declaration of 'A'
    // note: see declaration of 'A'
    // error C2079: 'public: static A const A::y' uses undefined struct 'A'
};

我的下一次尝试是声明一个'常量'类(隐式转换为数据类,此处未显示)。这似乎工作正常:

struct B_constant {
    constexpr B_constant(float x) : _x(x) {}
    float _x;
};

struct B {
    static constexpr B_constant y = B_constant(1.f);
};

但它有点难看,所以我想我会尝试将常量类作为数据类的嵌套类,但这样做工作:

struct C {
    struct C_constant {
        constexpr C_constant(float x) : _x(x) {}
        float _x;
    };

    static constexpr C_constant y = C_constant(1.f);
    // gcc-5.1:
    // error: 'constexpr C::C_constant::C_constant(float)' called in a constant expression
    // static constexpr C_constant y = C_constant(1.f);
    //                                               ^
    // msvc-14:
    // error C2131: expression did not evaluate to a constant
    // note: failure was caused by call of undefined function or one not declared 'constexpr'
    // note: see usage of 'C::C_constant::C_constant'
};

我注意到失败类似于声明constexpr构造函数时的错误,但是在数据类中使用它之后定义它:

struct D_constant {
    constexpr D_constant(float x);
    float _x;
};

struct D {
    static constexpr D_constant y = D_constant(1.f);
    // gcc-5.1:
    // error: 'constexpr D_constant::D_constant(float)' used before its definition
    // static constexpr D_constant y = D_constant(1.f);  
    //                                               ^
    // msvc-14:
    // error C2131: expression did not evaluate to a constant
    // note: failure was caused by call of undefined function or one not declared 'constexpr'
    // note: see usage of 'D::D_constant::D_constant'
};

constexpr D_constant::D_constant(float x) : _x(x) {}

任何人都可以了解第三个例子的情况吗?尽管嵌套类声明已完成,但似乎编译器无法在嵌套类中找到constexpr构造函数的定义。有谁知道一个更好的方法来完成我想要做的事情?

2 个答案:

答案 0 :(得分:0)

如上所述here

  

在类说明符的结束时,类被视为完全定义的对象类型(或完整类型)。 [...]否则在其自己的类成员规范中被认为是不完整的。

其中[...]是未提及嵌套类的异常列表。

This定义成员规范

  

类定义中的成员规范声明了该类的完整成员集;其他任何成员都无法添加。类的成员是数据成员,成员函数,嵌套类型,枚举器以及其成员模板和特化。 [...]

因此,嵌套类被认为是类规范的一部分,只有在您拥有完整类型(即结束}时,才会引用它们,并将所提到的异常放在一边)。
数据成员也是成员规范的一部分,在声明此成员时,必须将该类视为不完整 请注意,使用名称C_constant,您实际上使用的是限定名C::C_constant,这是C定义的一部分。 <{1}}中可以使用较短标识符引用它的事实不会改变其性质。

答案 1 :(得分:0)

  

有谁知道有更好的方法来完成我想要做的事情?

A::y对象而不是函数或函子可能并不重要。 如果没有,你可以解决障碍,如:

struct A {
    constexpr A(float x) : _x(x) {}
    float _x;

    static constexpr A y() {
        return A(1.f);
    }
};

constexpr A y = A::y();
static_assert(y._x == 1.f,"");