c++ - 编译时生成应在构造函数中创建的非 constexpr 对象的数组

标签 c++ arrays enums c++17 compile-time

你已经做了一个结构示例,它看起来像这样:

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

这是基于我之前使用此功能的情况。我不确定这是否是正确的方法。

我在 Visual Studio 中遇到的错误是:

1>o:\projects\cpptest\cpptest\cpptest\arraywiththis.cpp(30): error C2760: syntax error: unexpected token '{', expected 'expression'
1>o:\projects\cpptest\cpptest\cpptest\arraywiththis.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:\projects\cpptest\CPPTest\CPPTest> 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) 为什么是 void?

我想做的事情可能吗?如果是,如何修复我的代码?

最佳答案

你有多余的括号;可能是:

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

关于c++ - 编译时生成应在构造函数中创建的非 constexpr 对象的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59410362/

相关文章:

c++ - 是否可以使用 CUDA 来有效计算排序数组内元素的频率?

Javascript - 在数组中插入唯一元素 : Multidimensional check x Temporary unidimensional array

arrays - PThread 的分布式计算不工作

python - 如何在 Python 中的不等间距值之间创建等间距值?

c++ - 不明白 array-1 是什么意思

c++ - 如何在 webkit 浏览器控件中返回指向 JavaScript 的 IDispatch 指针

json - 使用 serde_json 将内部枚举值从 &str 反序列化为 u64

ios - 如何在 UserDefaults swift 中设置枚举数组

c++ - union 成员(member)地址需要说明

c# - 强制派生类实现接口(interface)