2013-05-20 2 views
3

Есть ли простой способ получить кусочек массива в C++?Slicing std :: array

То есть, у меня есть

array<double, 10> arr10; 

и хотите получить массив, состоящий из пяти первых элементов arr10:

array<double, 5> arr5 = arr10.??? 

(кроме пополнения его перебирая первого массива)

+0

Пара итераторов - это самый близкий C++ к фрагменту. Что-то вроде Boost.Range также позволяет упаковать их вместе в один объект, подобный срезу. –

ответ

3

Конструкторы для std::array неявно определены, поэтому вы не можете инициализировать его другим контейнером или диапазоном от итераторов. Самое близкое, что вы можете получить, это создать вспомогательную функцию, которая будет следить за копированием во время построения. Это позволяет однофазную инициализацию, которая, как я считаю, вы пытаетесь достичь.

template<class X, class Y> 
X CopyArray(const Y& src, const size_t size) 
{ 
    X dst; 
    std::copy(src.begin(), src.begin() + 5, dst.begin()); 
    return dst; 
} 
std::array<int, 5> arr5 = CopyArray<decltype(arr5)>(arr10, 5); 

Вы также можете использовать что-то вроде std::copy или перебирать копию себя.

std::copy(arr10.begin(), arr10.begin() + 5, arr5.begin()); 
2

Несомненно. Написал это:

template<int> struct seq {}; 
template<typename seq> struct seq_len; 
template<template<int...>class seq,int s0,int...s> 
struct seq_len<seq<s0,s...>>:std::integral_constant<std::size_t,seq_len<seq<s...>>::value> {}; 
template<template<int...>class seq,> 
struct seq_len<seq<>:std::integral_constant<std::size_t,0> {}; 
template<int Min, int Max, int... s> 
struct make_seq: make_seq<Min, Max-1, Max-1, s...> {}; 
template<int Min, int... s> 
struct make_seq<Min, Min, s...> { 
    typedef seq<s...> type; 
}; 
template<int Max, int Min=0> 
using MakeSeq = typename make_seq<Min,Max>::type; 

template<std::size_t src, typename T, int... indexes> 
std::array<T, sizeof...(indexes)> get_elements(seq<indexes...>, std::array<T, src > const& inp) { 
    return { inp[indexes]... }; 
} 
template<int len, std::size_t src, typename T> 
auto first_elements(std::array<T, src > const& inp) 
    -> decltype(get_elements(inp, MakeSeq<len>()) 
{ 
    return get_elements(inp, MakeSeq<len>()); 
} 

Если во время компиляции indexes... делает переназначение и MakeSeq делает SEQ от 0 до N-1.

Это поддерживает как произвольный набор индексов (через get_elements), так и первый n (через first_elements).

Использование:

std::array< int, 10 > arr = {0,1,2,3,4,5,6,7,8,9}; 
std::array< int, 6 > slice = get_elements(arr, seq<2,0,7,3,1,0>()); 
std::array< int, 5 > start = first_elements<5>(arr); 

, который избегает всех петель, либо явных или неявных.