在 C++11 中创建 N 元素 constexpr 数组

问题描述 投票:0回答:10

你好,我正在学习 C++11,我想知道如何制作 constexpr 0 到 n 数组,例如:

n = 5;

int array[] = {0 ... n};

所以数组可能是

{0, 1, 2, 3, 4, 5}

c++ c++11 constexpr array-initialization
10个回答
67
投票

在 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';
}

57
投票

与问题评论中的答案不同,您可以在没有编译器扩展的情况下执行此操作。

#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
}

37
投票

基于@Xeo的优秀想法,这里有一种方法可以让你填充数组

  • constexpr std::array<T, N> a = { fun(0), fun(1), ..., fun(N-1) };
  • 其中
    T
    是任何文字类型(不仅仅是
    int
    或其他有效的非类型模板参数类型),还可以是
    double
    std::complex
    (从 C++14 开始)
  • 其中
    fun()
    是任意
    constexpr
    函数
  • 从 C++14 开始由
    std::make_integer_sequence
    支持,但现在可以使用 g++ 和 Clang 轻松实现(请参阅答案末尾的实时示例)
  • 我在 GitHub 上使用@JonathanWakely 的实现(Boost 许可证)

这是代码

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, ", ")); 
}

实例


6
投票

使用C++14积分序列,或其不变的索引序列

#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;
}

1
投票
#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];
}

1
投票

对于 C++17 中的 std::array, constexpr 函数也被接受 请注意,var 'arr' 必须由 constexpr 进行初始化
(初始化:与@abyx的答案含义相同)

#include <array>
constexpr std::array<int, 3> get_array()
{
    std::array<int, 3> arr{0};
    arr[0] = 9;
    return arr;
}
static_assert(get_array().size() == 3);

1
投票

使用 C++17 可以轻松完成此操作,因为

std::array::begin
被标记为
constexpr

template<std::size_t N> std::array<int, N + 1> constexpr make_array()
{
    std::array<int, N + 1> tempArray{};
    int count = 0;
    for(int &elem:tempArray)
    {
        elem = count++;
    }
    return tempArray;
}
int main()
{
    
    //-------------------------------vv------>pass the size here 
    constexpr auto arr  = make_array<5>();
   
    //lets confirm if all objects have the expected value 
    for(const auto &elem: arr)
    {
        std::cout << elem << std::endl; //prints 1 2 3 4 5 with newline in between
    }
    
}

演示


0
投票
#include <iostream>
#include <array>

template <typename Arg, typename ... Args>
constexpr std::array <Arg, ((sizeof ... (Args)) + 1)> MakeArray (const Arg& arg, Args ... args)
{
    return { arg, args ...  };
}

void PrintArray (const auto& arr)
{   
    for (auto ii = 0; ii < arr.size (); ++ii)
    {
        std::cout << arr[ii] << "\n";
    }
    std::cout << "\n";
}

int main()
{
    PrintArray (MakeArray (0, 1, 2, 3));
    PrintArray (MakeArray ('a', 'b', 'c'));
    PrintArray (MakeArray (1.5, 2.5, 3.5));

    return 0;
}

-2
投票

使用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;
 }

输出:

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

-5
投票
© www.soinside.com 2019 - 2024. All rights reserved.