2017-01-15 33 views
17

我該如何構建一個帶索引序列的std::array或者依賴於順序索引的lambda?如何用索引序列構造一個std ::數組?

std::iotastd::generate似乎有關,但我不知道如何使用它們來構建std::array,而不是應用它們在其上已建成一個(這是不可能的情況下,陣列ISN的元素類型'default-constructible)。

那種代碼Example我想幹:

#include <array> 

class C 
{ 
public: 
    C(int x, float f) : m_x{x}, m_f{f} {} 
private: 
    int m_x; 
    float m_f; 
}; 

int main() 
{ 
    std::array<int, 10> ar = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 
    std::array<C, 3> ar2 = {C{0, 1.0}, C{1, 1.0}, C{2, 1.0}}; 
    return 0; 
} 
+0

在構建'std :: array'的元素(通過索引或任何其他方法)之前,不可能對它進行迭代。您可以嘗試聚合初始化。 – Peter

+1

一些代碼顯示你希望達到的目的。 – StoryTeller

+0

@StoryTeller新增 – Danra

回答

11

對於ar,這裏是一個辦法:

namespace detail { 
    template<typename T, T... Ns> 
    constexpr auto make_iota_array(T const offset, std::integer_sequence<T, Ns...>) noexcept 
    -> std::array<T, sizeof...(Ns)> { 
    return {{(Ns + offset)...}}; 
    } 
} 

template<typename T, T N> 
constexpr auto make_iota_array(T const offset = {}) noexcept { 
    static_assert(N >= T{}, "no negative sizes"); 
    return detail::make_iota_array<T>(offset, std::make_integer_sequence<T, N>{}); 
} 

// ... 

auto ar = make_iota_array<int, 10>(99); 

Online Demo

對於ar2,這裏是一個辦法:

namespace detail { 
    template<typename T, typename F, std::size_t... Is> 
    constexpr auto generate_array(F& f, std::index_sequence<Is...>) 
    -> std::array<T, sizeof...(Is)> { 
    return {{f(std::integral_constant<std::size_t, Is>{})...}}; 
    } 
} 

template<typename T, std::size_t N, typename F> 
constexpr auto generate_array(F f) { 
    return detail::generate_array<T>(f, std::make_index_sequence<N>{}); 
} 

// ... 

auto ar2 = generate_array<C, 3>([](auto i) -> C { return {i, i * 1.12f}; }); 

Online Demo

noexcept是更多或更少的可選這裏IMO,這裏不再贅述,但出現在演示中)。

N.b.兩者都完全是constexpr,但由於generate_array很可能與lambda一起使用,所以在實踐中不會constexpr直到C++ 17(demo)。另外n.b.由於guaranteed copy elisiondemo),generate_array將與C++ 17中的非可複製/不可移動類型一起使用。

+0

這與Edgar的答案有相同的問題,它不起作用對於沒有複製構造函數的類 – Danra

+0

@Danra:好的,那麼..?你的問題在任何方面都沒有提到可複製類型是一個問題。 – ildjarn

+0

我正在尋找一種通用方法。這對於不可複製的返回類型不起作用的事實是一個限制。 – Danra

14

下一個方法應該爲你工作:

template<typename T, std::size_t N, std::size_t... I> 
constexpr auto create_array_impl(std::index_sequence<I...>) { 
    return std::array<T, N>{ {I...} }; 
} 

template<typename T, std::size_t N> 
constexpr auto create_array() { 
    return create_array_impl<T, N>(std::make_index_sequence<N>{}); 
} 

您可以創建這樣一個數組:

constexpr auto array = create_array<std::size_t, 4>(); 

wandbox example

一個可以修改上述方案,以在未來的方式添加拉姆達:

template<typename T, std::size_t N, typename F, std::size_t... I> 
constexpr auto create_array_impl(F&& func, std::index_sequence<I...>) { 
    return std::array<T, N>{ {func(I)...} }; 
} 

template<typename T, std::size_t N, typename F> 
constexpr auto create_array(F&& func) { 
    return create_array_impl<T, N>(std::forward<F>(func), std::make_index_sequence<N>{}); 
} 

然後用:

const auto array = create_array<std::size_t, 4>([](auto e) { 
    return e * e; 
}); 

wandbox example

+0

從依賴於順序索引的lambda構造的情況如何? – Danra

+0

@丹拉我修改了答案。 –

+0

如果該函數返回一個不可複製的類http://melpon.org/wandbox/permlink/ld6OcmMdKyNVom5m,它似乎不工作,任何想法如何解決這個問題? – Danra

相關問題