初始化 reference_wrapper 的数组
Initialize an array of reference_wrapper
从 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>
和 return 对这些片段的引用,然后放入 _board
。但是,我的 _board
的以下初始化会产生
no default constructor exists for class "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
不是默认可构造的。
因此您必须编写自己的变通函数。我将 post 编写初始化引用数组的一般问题的代码,不会深入探讨您的问题。
因此请考虑以下情况:您有一个数组 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
并将 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]
的 const 引用,对于向量也是如此(但请注意对矢量通常不稳定,即通过调整大小或类似操作它们可能会失效)。
从 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>
和 return 对这些片段的引用,然后放入 _board
。但是,我的 _board
的以下初始化会产生
no default constructor exists for class "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
不是默认可构造的。
因此您必须编写自己的变通函数。我将 post 编写初始化引用数组的一般问题的代码,不会深入探讨您的问题。
因此请考虑以下情况:您有一个数组 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
并将 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]
的 const 引用,对于向量也是如此(但请注意对矢量通常不稳定,即通过调整大小或类似操作它们可能会失效)。