编译时生成应在构造函数中创建的非 constexpr 对象数组
Compile-time generating an array of non-constexpr objects that should be created in constructor
你已经做了一个结构的例子,它看起来像这样:
#include <array>
enum class ItemType
{
Tree,
Bush,
Flower,
Grass,
Mushroom,
CountOfTypes
};
class Items;
class Item
{
public:
Item(Items* parentContainer, ItemType type) : parentContainer(parentContainer), type(type) { DoSomething(); }
ItemType type;
// Parent container needs to be acessed occasionally
Items* parentContainer;
// This cannot be constexpr
void DoSomething();
};
class Items
{
public:
using ItemArray = std::array<Item, ItemType::CountOfTypes>;
// Should contain one item per type, at index equal to that type
ItemArray items;
};
请注意对数组内容的要求,对于items
数组必须始终如此:
ItemType someType = ... any of item type enum except of CountOfTypes ...;
/// must be true
items[(size_t)someType].type == someType;
这段代码不会编译,因为Item
没有默认的构造函数,但我们尝试在Items::Items
中分配它。即使它确实编译了,这些值也将是未初始化的,我们不希望这样。
解决该问题的一种选择是以正确的顺序手动枚举类型:
class Items
{
public:
Item items[(size_t)ItemType::CountOfTypes] = { {this, ItemType::Tree}, {this, ItemType::Bush}, {this, ItemType::Grass}, {this, ItemType::Mushroom} };
};
另一种选择是向Item
添加一个默认构造函数,然后调用一些初始化函数。我也不喜欢这样。
但是我过去用过几次std::make_integer_sequence
,我想再试一次。如果上面的代码有效,应该有一些序列来生成它。因此,我尝试了这个:
class Items
{
public:
using ItemArray = std::array<Item, (size_t)ItemType::CountOfTypes>;
template <int... Indices>
static ItemArray GenerateItems(std::integer_sequence<int, Indices...>, Items* parent) { return { ({parent, Indices})... }; }
ItemArray items = GenerateItems(std::make_integer_sequence<int, static_cast<int>(ItemType::CountOfTypes)>{}, this);
};
这是基于我以前对此功能的用法。我不确定这是否是正确的方法。
我在视觉工作室中遇到的错误是:
1>o:projectscpptestcpptestcpptestarraywiththis.cpp(30): error C2760: syntax error: unexpected token '{', expected 'expression'
1>o:projectscpptestcpptestcpptestarraywiththis.cpp(30): note: This diagnostic occurred in the compiler generated function 'Items::ItemArray Items::GenerateItems(std::integer_sequence<int,Indices...>,Items *)'
GCC 更加直言不讳(他们的错误消息在过去 6 年中得到了难以想象的改进(:
PS O:projectscpptestCPPTestCPPTest> g++ .ArrayWithThis.cpp
.ArrayWithThis.cpp: In static member function 'static Items::ItemArray Items::GenerateItems(std::integer_sequence<int, Indices ...>, Items*)':
.ArrayWithThis.cpp:30:117: error: expected ';' before '}' token
static ItemArray GenerateItems(std::integer_sequence<int, Indices...>, Items* parent) { return { ({parent, Indices})... }; }
^
;
.ArrayWithThis.cpp: In instantiation of 'static Items::ItemArray Items::GenerateItems(std::integer_sequence<int, Indices ...>, Items*) [with int ...Indices = {0, 1, 2, 3}; Items::ItemArray = std::array<Item, 4>]':
.ArrayWithThis.cpp:32:116: required from here
.ArrayWithThis.cpp:30:123: error: could not convert '{((void)0, 0), ((void)0, 1), ((void)0, 2), ((void)0, 3)}' from '<brace-enclosed initializer list>' to 'Items::ItemArray' {aka 'std::array<Item, 4>'}
static ItemArray GenerateItems(std::integer_sequence<int, Indices...>, Items* parent) { return { ({parent, Indices})... }; }
这尤其困扰着我:((void)0, 0)
为什么是空的?
我正在尝试做的事情可能吗?如果是,如何修复我的代码?
您有多余的括号;它可能是:
class Items
{
public:
static constexpr std::size_t ItemCount = static_cast<std::size_t>(ItemType::CountOfTypes);
using ItemArray = std::array<Item, ItemCount>;
template <std::size_t ... Is>
static ItemArray GenerateItems(std::index_sequence<Is...>, Items* parent)
{ return {{ Item{parent, Indices}... }}; }
ItemArray items = GenerateItems(std::make_index_sequence<ItemCount>{}, this);
};
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 使用std::multimap迭代器创建std::list
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 使用CMake创建QML插件
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 多成员Constexpr结构初始化
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 试图在visual studio上用C++创建一个桌面应用程序
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- 编译时生成应在构造函数中创建的非 constexpr 对象数组
- 基于模式创建位掩码作为 constexpr
- 如何在C 中创建ConstexPR函数
- 通过在 constexpr 构造函数中传递 N,在编译时创建一个大小为 N 的数组
- 使用C constexpr可以创建符号重复
- 在不创建参数对象的情况下解析constexpr函数
- 不能创建constexpr std::vector