在C ++ 11中创buildN元素constexpr数组
你好我正在学习C ++ 11,我想知道如何使一个constexpr 0到n数组,例如:
n = 5; int array[] = {0 ... n};
所以数组可能是{0, 1, 2, 3, 4, 5}
不像那些在你的问题的评论中的答案,你可以做到这一点没有编译器扩展。
#include <iostream> template<int N, int... Rest> struct Array_impl { static constexpr auto& value = Array_impl<N - 1, N, Rest...>::value; }; template<int... Rest> struct Array_impl<0, Rest...> { static constexpr int value[] = { 0, Rest... }; }; template<int... Rest> constexpr int Array_impl<0, Rest...>::value[]; template<int N> struct Array { static_assert(N >= 0, "N must be at least 0"); static constexpr auto& value = Array_impl<N>::value; Array() = delete; Array(const Array&) = delete; Array(Array&&) = delete; }; int main() { std::cout << Array<4>::value[3]; // prints 3 }
基于@ Xeo的出色思想 ,这里是一个让你填充数组的方法
-
constexpr std::array<T, N> a = { fun(0), fun(1), ..., fun(N-1) };
- 其中
T
是任何文字types(不只是int
或其他有效的非types模板参数types),还有double
或std::complex
(从C ++ 14开始) -
fun()
是任何constexpr
函数 - 这是从C ++ 14开始支持的
std::make_integer_sequence
,但是现在用g ++和Clang很容易实现(参见答案最后的实例) - 我使用@JonathanWakely 在GitHub (Boost License) 上的实现,
这是代码
template<class Function, std::size_t... Indices> constexpr auto make_array_helper(Function f, std::index_sequence<Indices...>) -> std::array<typename std::result_of<Function(std::size_t)>::type, sizeof...(Indices)> { return {{ f(Indices)... }}; } template<int N, class Function> constexpr auto make_array(Function f) -> std::array<typename std::result_of<Function(std::size_t)>::type, N> { return make_array_helper(f, std::make_index_sequence<N>{}); } constexpr double fun(double x) { return x * x; } int main() { constexpr auto N = 10; constexpr auto a = make_array<N>(fun); std::copy(std::begin(a), std::end(a), std::ostream_iterator<double>(std::cout, ", ")); }
现场示例
在C ++ 14中,可以使用constexpr
构造函数和循环轻松完成:
#include <iostream> template<int N> struct A { constexpr A() : arr() { for (auto i = 0; i != N; ++i) arr[i] = i; } int arr[N]; }; int main() { constexpr auto a = A<4>(); for (auto x : a.arr) std::cout << x << '\n'; }
使用C ++ 14的integral_sequence或其不变的index_sequence
#include <iostream> template< int ... I > struct index_sequence{ using type = index_sequence; using value_type = int; static constexpr std::size_t size()noexcept{ return sizeof...(I); } }; // making index_sequence template< class I1, class I2> struct concat; template< int ...I, int ...J> struct concat< index_sequence<I...>, index_sequence<J...> > : index_sequence< I ... , ( J + sizeof...(I) )... > {}; template< int N > struct make_index_sequence_impl; template< int N > using make_index_sequence = typename make_index_sequence_impl<N>::type; template< > struct make_index_sequence_impl<0> : index_sequence<>{}; template< > struct make_index_sequence_impl<1> : index_sequence<0>{}; template< int N > struct make_index_sequence_impl : concat< make_index_sequence<N/2>, make_index_sequence<N - N/2> > {}; // now, we can build our structure. template < class IS > struct mystruct_base; template< int ... I > struct mystruct_base< index_sequence< I ... > > { static constexpr int array[]{I ... }; }; template< int ... I > constexpr int mystruct_base< index_sequence<I...> >::array[] ; template< int N > struct mystruct : mystruct_base< make_index_sequence<N > > {}; int main() { mystruct<20> ms; //print for(auto e : ms.array) { std::cout << e << ' '; } std::cout << std::endl; return 0; } output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
更新:你可以使用std :: array:
template< int ... I > static constexpr std::array< int, sizeof...(I) > build_array( index_sequence<I...> ) noexcept { return std::array<int, sizeof...(I) > { I... }; } int main() { std::array<int, 20> ma = build_array( make_index_sequence<20>{} ); for(auto e : ma) std::cout << e << ' '; std::cout << std::endl; }
#include <array> #include <iostream> template<int... N> struct expand; template<int... N> struct expand<0, N...> { constexpr static std::array<int, sizeof...(N) + 1> values = {{ 0, N... }}; }; template<int L, int... N> struct expand<L, N...> : expand<L-1, L, N...> {}; template<int... N> constexpr std::array<int, sizeof...(N) + 1> expand<0, N...>::values; int main() { std::cout << expand<100>::values[9]; }
使用boost预处理器,它非常简单。
#include <cstdio> #include <cstddef> #include <boost/preprocessor/repeat.hpp> #include <boost/preprocessor/comma_if.hpp> #define IDENTITY(z,n,dummy) BOOST_PP_COMMA_IF(n) n #define INITIALIZER_n(n) { BOOST_PP_REPEAT(n,IDENTITY,~) } int main(int argc, char* argv[]) { int array[] = INITIALIZER_n(25); for(std::size_t i = 0; i < sizeof(array)/sizeof(array[0]); ++i) printf("%d ",array[i]); return 0; }
OUTPUT: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
试试boost::mpl::range_c<int, 0, N>
docs 。