初始化reference_wrapper数组

Initialize an array of reference_wrapper

本文关键字:数组 wrapper reference 初始化      更新时间:2023-10-16

从C到C++,我试图理解智能指针和引用的世界。我有以下几点:

class Game {
public:
...
private:
...
static GamePiece EmptyPiece;
reference_wrapper<GamePiece> _board[N][M] = { ref(Game::EmptyPiece) };
vector<GamePlayer> _players = vector<GamePlayer>(N_PLAYERS, GamePlayer());
...
};

在以下情况下,我希望每个Player都持有一个vector<GamePiece>并返回对这些片段的引用,然后放入_board中。但是,我的_board的以下初始化会产生

类"std::reference_wrapper 不存在默认构造函数

我在这里错过了什么?在所有权方面,每个GamePlayer都归Game所有(可以看出),GamePiece肯定归GamePlayer所有,这就是为什么我想使用引用。

就是这里

reference_wrapper<GamePiece> _board[N][M] = { ref(Game::EmptyPiece) };

您初始化第一个元素(加入一些大括号省略号),但保留其余默认值初始化。这不可能发生,因为std::reference_wrapper不能默认初始化(就像它建模的引用一样)。

您可以将原始数组替换为N*M大小的std::vector,并使用适当的构造函数来复制初始化所有元素(就像您对_players所做的那样)。当然,您需要自己进行索引计算,但内存将按顺序布局。

在我看来,初始化引用数组很痛苦。问题是 - 正如@StoryTeller的回答中所述 -reference_wrapper不是默认可构造的。

因此,您必须编写自己的解决方法函数。我将发布初始化引用数组的一般问题的代码,不会深入探讨您的问题。

因此,请考虑以下情况:您有一个数组arr其中包含支持operator[]的某种类型的元素(例如,您的问题中的Game)。您需要一个常量或非常量引用数组,这些引用由索引ind指定的此数组中的元素。给你:

template<typename arr_t, size_t ... I>
auto get_const_reference_array(arr_t const& arr, std::array<size_t, sizeof ...(I)> const& ind, std::index_sequence<I...>)
{
using T = std::decay_t<decltype(std::declval<arr_t>().operator[](size_t{}))>;
return std::array<std::reference_wrapper<const T>, sizeof ...(I)> { std::cref(arr[std::get<I>(ind)]) ... };
}
template<typename arr_t, size_t dim>
auto get_const_reference_array(arr_t const& arr, std::array<size_t, dim> const& ind)
{
return get_const_reference_array(arr, ind, std::make_index_sequence<dim>{});
}

对于非 const 版本,请删除此代码中的所有const,并将std::cref替换为std::ref

将其用作

std::array<int,5> arr{{1,3,5,7,9}};
std::array<size_t,2> ind{{1,3}};
auto ref_arr = get_const_reference_array(arr, ind);
std::vector<int> vec{{1,3,5,7,9}};
auto ref_vec = get_const_reference_array(vec, ind);

然后ref_arr是一个大小2数组,其中包含对arr[1]arr[3]的常量引用,对于向量也是如此(但请注意,对向量的引用通常不稳定,即通过调整大小或类似的操作,它们可能会失效)。