你好我正在學習C++ 11,我想知道如何使一個constexpr 0到n陣列,例如:創建N元件陣列constexpr C++ 11
n = 5;
int array[] = {0 ... n};
所以陣列可能是{0, 1, 2, 3, 4, 5}
你好我正在學習C++ 11,我想知道如何使一個constexpr 0到n陣列,例如:創建N元件陣列constexpr C++ 11
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
}
@Kal很好,但「only」適用於'int'或其他類型,可以顯示爲非類型模板參數(因此不適用於例如'double')。查看我的答案以獲得一般解決方案。 – TemplateRex
不錯。但是我想我會隱藏非可變公共接口後面的遞歸可變參數模板,以避免有人嘗試'Array <9,3,5>'時發生混淆。 – aschepler
使用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
UPDATE: 您可以使用std ::數組:
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;
}
哪個編譯器支持這個? – TemplateRex
Clang + libC++提示樹支持這個。通過'-std = C++ 1y'。 –
我使用Clang 3.3和GCC 4.8。1與-std = C++ 11選項。 –
基於@ XEO的excellent idea,這裏有一種方法可以讓你填充一組數字
constexpr std::array<T, N> a = { fun(0), fun(1), ..., fun(N-1) };
T
是任何文本類型(不只是int
或其他有效的非類型模板參數類型),也double
,或std::complex
(從C++ 14以後)fun()
是任何constexpr
功能std::make_integer_sequence
從C++ 14向前今天支持,但很容易地實現與
下面是代碼
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, ", "));
}
使用升壓預處理
'在哪裏汽車是任何文字類型'是不是'文字類型的'std :: array',在'auto a = make_array
#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];
}
,這是非常簡單的。
#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
我想你也可以使用'ENUM'宏中的一個,例如'BOOST_PP_ENUM_PARAMS(25,BOOST_PP_EMPTY())',而不是'REPEAT' +'COMMA_IF' – dyp
在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';
}
嘗試boost::mpl::range_c<int, 0, N>
docs。
[這是最近類似的問題](http://stackoverflow.com/q/19016099/420683)使用'std :: array's。 – dyp