2015-08-24 25 views
15

Tôi có một std::array<Foo, 10> và tôi muốn tạo một std::array<Bar, 10> sử dụng hàm từ Foo đến Bar. Thông thường tôi sẽ sử dụng std::transform như vậy:Cách tạo std :: array với std :: transform mà không có hàm tạo mặc định

array<Bar, 10> bars; 
transform(foos.begin(), foos.end(), bars.begin(), [](Foo foo){ 
    return Bar(foo.m_1, foo.m_2); 
}); 

Tuy nhiên, Bar không có một constructor mặc định, vì vậy tôi không thể tạo ra các mảng bars. Tôi luôn có thể sử dụng vector nhưng nó sẽ là tốt đẹp để có thể sử dụng array để đảm bảo rằng tôi luôn luôn có chính xác 10 yếu tố. Điều đó có thể không?

+0

Bạn có thể sử dụng một cái gì đó như [chưa hoàn toàn] (https://www.reddit.com/r/cpp/comments/1njair/stdoptional_and_stddynarray_removed_from_c14_and/) -std [std :: tùy chọn] (https://github.com/akrzemi1/Optional) để bọc thanh cho các mục đích của mảng này. Ít nhất thì điều đó sẽ không buộc Bar có một hàm tạo mặc định nói chung, và nó có ích bao gồm trong một dự án nào đó (imo). – HostileFork

+1

Có phải 'vectơ.reserve (10)' không đủ trong mã của bạn cho kích thước '10' hay bạn muốn đảm bảo mã máy khách cũng không thay đổi kích thước đó? – Niall

+0

Trong trường hợp này 'vector.reserve' hoạt động tốt nhưng không phải là ý tưởng, vì ngữ nghĩa bộ sưu tập này phải có 10 mục và nó sẽ không hoạt động trong mọi trường hợp. Hình ảnh nếu tôi phải chuyển nó đến một hàm chấp nhận một 'std :: array &'. – Drew

Trả lời

14

Không có std::transform, nhưng không có ma thuật mẫu nhỏ nào không thể khắc phục được.

template<std::size_t N, std::size_t... Is> 
std::array<Bar, N> foos_to_bars(const std::array<Foo, N>& foos, 
           std::index_sequence<Is...>) { 
    return {{ Bar(foos[Is].m_1, foos[Is].m_2)... }}; 
} 

template<std::size_t N, std::size_t... Is> 
std::array<Bar, N> foos_to_bars(const std::array<Foo, N>& foos) { 
    return foos_to_bars(foos, std::make_index_sequence<N>()); 
} 

std::index_sequence và bạn bè là C++ 14, nhưng dễ dàng triển khai trong C++ 11. Có lẽ một nửa tá triển khai trên SO một mình.

+0

Tại sao các dấu ngoặc kép trong câu lệnh return của 'foos_to_bars'? Nó có liên quan đến việc tạo ra một bối cảnh mở rộng gói không? Nếu như vậy là '{{...}}' tốt hơn những cái khác mà bạn đã trình bày trong SO (ví dụ 'expander')? –

+1

@NikosAthanasiou Nah, chỉ im lặng một số cảnh báo "thiếu dấu ngoặc ôm" của trình biên dịch. ('std :: array' là một tổng hợp có chứa một mảng tích hợp, các dấu ngoặc ngoài là' std :: array'; bên trong cho phần tử dựng sẵn. Bạn được phép bỏ ẩn các dấu ngoặc bên trong, nhưng một số trình biên dịch cảnh báo nếu bạn làm điều đó.) –

Các vấn đề liên quan