我正在尝试编译此代码,但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在封闭的命名空间中创建一个非成员.
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)
这个对类似问题的回答表明,事实上,这是可能的.您只需将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不喜欢它,但它可以正确编译!).
如果您接受具有功能而不是变量,则可以
struct Cursor
{
size_t row,column;
static constexpr Cursor ZERO() { return Cursor{0,0}; }
};
Run Code Online (Sandbox Code Playgroud)