如果我有一个constexpr
整数数组,长度为N
,我该如何将它转换成适当的constexpr std::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
数组的大小可以在编译时推断,因此您不必显式指定大小。该大小可用于内部创建一组索引,以从数组中获取元素并即时创建元组。
如评论中所述,如果要更一般化并接受原始数组和std::array
,可以这样做:#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
那样做。如果你愿意,我可以更新我的回答来涵盖它们。 - skypjack////////////////////////////////////////////////////////////////////////////////////////////////////
// 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>{}));
}
index_sequence_for
来代替。 - Kerrek SB
std::array
或其他类型? - Cheers and hth. - Alf