C++ static constexpr字段,类型不完整

lod*_*odo 27 c++ c++11

我正在尝试编译此代码,但g ++抱怨ZERO有一个不完整的类型.这是否意味着在C++中结构不能包含static constexpr自身的实例?如果是这样,为什么?

struct Cursor
{
    size_t row,column;

    static constexpr Cursor ZERO {0,0};
    //error: constexpr const Cursor Cursor::ZERO has incomplete type
};
Run Code Online (Sandbox Code Playgroud)

编辑:我明白,Cursor当我申报时,不能有完整的类型ZERO.我想知道的是:我有什么方法可以ZERO归属Cursor并且仍在存在constexpr吗?

Lig*_*ica 19

不幸的是,你根本做不到!

某些static constexpr成员可能是内联初始化的:

[C++11 9.4.2/3]: [..]static文字类型的数据成员可以在类定义与所声明的constexpr说明符; 如果是这样,它的声明应指定一个大括号或等于初始化器,其中作为赋值表达式的每个initializer子句都是一个常量表达式.[..]

Cursor 是一个文字类型,所以这很重要.

并且在自己的类型中使用Cursor自身作为static数据成员不是问题,只要在词法命名空间范围初始化它:

[C++11: 9.4.2/2]: static在类定义中声明数据成员不是定义,除了cv-qualified void之外,可能是不完整的类型.数据成员的定义static应出现在包含成员类定义的命名空间范围内.在命名空间范围的定义中,static数据成员的名称应使用::运算符通过其类名进行限定.数据成员定义中初始化表达式在static其类的范围内(3.3.7).

但你不能这样做constexpr:

[C++11: 7.1.5/9]:constexpr对象声明中使用的说明符将对象声明为const.这样的对象应具有文字类型并应初始化.[..]

我认为所有这些措辞都可以改进,但与此同时,我认为你将不得不ZERO在封闭的命名空间中创建一个非成员.

  • 谢谢你这个完整的答案.鉴于Cursor实际上是在VGA类中定义的,我只是让ZERO成为VGA的静态constexpr成员.有时我觉得某些限制很烦人...... (2认同)

Ben*_*igt 11

有什么办法可以让ZERO属于Cursor但仍然存在constexpr

是的,如果将嵌套的子类计为"属于"包含的类:

struct Cursor
{
    size_t row,column;

    struct Constants;
};

struct Cursor::Constants
{
    static constexpr Cursor ZERO {0,0};
};
Run Code Online (Sandbox Code Playgroud)


mon*_*506 8

这个对类似问题的回答表明,事实上,这是可能的.您只需将constexpr关键字与定义而不是声明放在一起:

#include <iostream>
#include <array>

struct Cursor
{
    static Cursor const ZERO;
    std::size_t row, column;
};

constexpr Cursor const Cursor::ZERO{ 0, 0 };

int main(int, char**) noexcept
{
    // using the values in a template argument ensure compile-time usage
    std::array<int, Cursor::ZERO.row> row_arr{};
    std::array<int, Cursor::ZERO.column> col_arr{};
    std::cout << "rows: " << row_arr.size() << "\ncols: " << col_arr.size();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用GCC(ideone),clang(rextester)和MSVC++ 2017 进行全面测试(请注意,IntelliSense不喜欢它,但它可以正确编译!).


gal*_*tte 7

如果您接受具有功能而不是变量,则可以

struct Cursor
{
    size_t row,column;

    static constexpr Cursor ZERO() { return Cursor{0,0}; }
};
Run Code Online (Sandbox Code Playgroud)