也就是说,给定constexpr std::array<int,2>{1,2}
并将其传递给某些吐出类型std::integer_sequence<int, 1, 2>
的函数或辅助类吗?
从类型世界跳到“ constexpr值”世界似乎很容易(例如,进行反向转换),但是很难或不可能进行反向。
答案 0 :(得分:9)
您似乎可以在C ++ 17中做到这一点,但要在调用站点引入lambda:
template <size_t N, typename F, size_t... indexes>
constexpr auto make_seq_helper(F f, std::index_sequence<indexes...> is) {
return std::integer_sequence<int, std::get<indexes>(f())...>{};
}
template <typename F>
constexpr auto make_seq(F f) {
constexpr size_t N = f().size();
using indexes = std::make_index_sequence<N>;
return make_seq_helper<N>(f, indexes{});
};
像这样呼叫make_seq
:
constexpr std::array a{7, 15, 28};
auto x = make_seq([](){ return a; });
产生类型为x
的{{1}}。我不确定是否可以删除lambda用法。
答案 1 :(得分:4)
如果数组具有外部链接,则可以执行以下操作:
template <auto& Arr, size_t... Is>
constexpr auto make_seq_impl(std::index_sequence<Is...>) {
using T = typename std::decay_t<decltype(Arr)>::value_type;
return std::integer_sequence<T, Arr[Is]...>{};
}
template <auto& Arr>
constexpr auto make_seq() {
return make_seq_impl<Arr>(std::make_index_sequence<Arr.size()>());
}
constexpr std::array a{7, 15, 28};
int main()
{
[[maybe_unused]]auto x = make_seq<a>();
static_assert(std::is_same<std::integer_sequence<int, 7, 15, 28>, decltype(x)>::value, "!");
}
或者,通过结构方式,您可以这样做:
template <const auto& Arr, typename Seq = std::make_index_sequence<std::size(Arr)>>
struct make_seq;
template <typename T, std::size_t N, const std::array<T, N>& Arr, std::size_t ... Is>
struct make_seq<Arr, std::index_sequence<Is...>>
{
using type = std::integer_sequence<T, Arr[Is]...>;
};
答案 2 :(得分:2)
这是C ++ 14兼容的解决方案。
将constexpr std::array
(或任何其他struct / class对象)作为模板参数“传递”的技巧是将其包装为类型:
constexpr std::array<int,3> a{7,15,28};
struct ArrayWrapper_a {
static constexpr auto& value = a;
};
template<typename ArrayWrapper>
struct Foobar {
// do stuff with ArrayWrapper::value
}
然后,您可以执行与BeeOnRope的答案类似的操作来生成序列:
template<typename ArrayWrapper, typename Sequence>
struct array_to_sequence_impl;
template<typename ArrayWrapper, std::size_t... indices>
struct array_to_sequence_impl<ArrayWrapper,std::index_sequence<indices...>> {
using value_type = typename std::decay_t<decltype(ArrayWrapper::value)>::value_type;
using type = std::integer_sequence<value_type, std::get<indices>(ArrayWrapper::value)...>;
};
template<typename ArrayWrapper>
using array_to_sequence = typename array_to_sequence_impl<ArrayWrapper,std::make_index_sequence<ArrayWrapper::value.size()>>::type;
用法:
constexpr std::array<int,3> a{7,15,28};
struct ArrayWrapper_a {
static constexpr auto& value = a;
};
using Sequence_a = array_to_sequence<ArrayWrapper_a>;