【发布时间】:2016-12-18 11:14:00
【问题描述】:
如果我有一个N 整数的constexpr 数组,如何将其转换为适当的constexpr std::tuple<...>?
【问题讨论】:
-
您的数组是原始数组还是
std::array还是什么? -
既然已经有了数组,为什么还要
tuple?
如果我有一个N 整数的constexpr 数组,如何将其转换为适当的constexpr std::tuple<...>?
【问题讨论】:
std::array 还是什么?
tuple?
以下是原始数组的可能实现:
#include<functional>
template<std::size_t... I, std::size_t N>
constexpr auto f(const int (&arr)[N], std::index_sequence<I...>) {
return std::make_tuple(arr[I]...);
}
template<std::size_t N>
constexpr auto f(const int (&arr)[N]) {
return f(arr, std::make_index_sequence<N>{});
}
int main() {
constexpr int arr[] = { 0, 1, 2 };
constexpr auto tup = f(arr);
static_assert(std::get<0>(tup) == 0, "!");
static_assert(std::get<1>(tup) == 1, "!");
static_assert(std::get<2>(tup) == 2, "!");
}
constexpr 数组的大小可以在编译时推导出来,因此您不必显式指定它。
该大小可以在内部用于创建一组索引,以从数组中取出元素并动态创建元组。
如 cmets 中所述,如果您想更概括一点并接受原始数组和std::arrays,您可以这样做:
#include<functional>
#include<array>
template<std::size_t... I, typename U>
constexpr auto f(const U &arr, std::index_sequence<I...>) {
return std::make_tuple(arr[I]...);
}
template<typename T, std::size_t N>
constexpr auto f(const T (&arr)[N]) {
return f(arr, std::make_index_sequence<N>{});
}
template<typename T, std::size_t N>
constexpr auto f(const std::array<T, N> &arr) {
return f(arr, std::make_index_sequence<N>{});
}
int main() {
constexpr int arr1[] = { 0, 1, 2 };
constexpr auto tup1 = f(arr1);
static_assert(std::get<0>(tup1) == 0, "!");
static_assert(std::get<1>(tup1) == 1, "!");
static_assert(std::get<2>(tup1) == 2, "!");
constexpr std::array<int, 3> arr2 = { 0, 1, 2 };
constexpr auto tup2 = f(arr2);
static_assert(std::get<0>(tup2) == 0, "!");
static_assert(std::get<1>(tup2) == 1, "!");
static_assert(std::get<2>(tup2) == 2, "!");
}
【讨论】:
std::array 那样做。如果你愿意,我也可以更新我的答案以涵盖它们。
将数组转换为元组利用std::integer sequence,在编译器调用 0..N 的辅助函数时在编译时构建数组索引。
这是演示这一点的代码。 http://coliru.stacked-crooked.com/a/b2d6c6ca1f5dc635
////////////////////////////////////////////////////////////////////////////////////////////////////
// tuple_from_array
namespace detail {
template<typename T, std::size_t... Is>
auto constexpr tuple_from_array(T const& arr, std::index_sequence<Is...>)
{
return std::make_tuple(arr[Is]...);
}
template<std::size_t N, typename V, typename T, std::size_t ...Is>
auto constexpr array_from_container(T const& c, std::index_sequence<Is...>)
{
return std::array<V, N>{c[Is]...};
}
} // ns detail
template<typename T>
auto constexpr tuple_from_array(T const& arr)
{
auto constexpr tup_size = std::tuple_size<std::decay_t<T>>::value;
return detail::tuple_from_array(arr, std::make_index_sequence<tup_size>{});
}
template<typename T, std::size_t N>
auto constexpr tuple_from_array(T const (&arr)[N])
{
return detail::tuple_from_array(arr, std::make_index_sequence<N>{});
}
// not safe
template<std::size_t N, typename T>
auto constexpr tuple_from_container(T const& c)
{
using V = typename T::value_type;
return tuple_from_array(detail::array_from_container<N, V>(c, std::make_index_sequence<N>{}));
}
编辑:我将 skypjack@ 的答案与我自己的答案结合起来,以涵盖在 cmets 中查询的基本数组。不过,这两天我不能把这个作为我自己的答案:(
【讨论】:
index_sequence_for 代替。