Với lặp truy cập ngẫu nhiên, và giả định một kích thước nhất định tại thời gian biên dịch, bạn có thể sử dụng một pack of indices để làm như vậy:
template <std::size_t... Indices>
struct indices {
using next = indices<Indices..., sizeof...(Indices)>;
};
template <std::size_t N>
struct build_indices {
using type = typename build_indices<N-1>::type::next;
};
template <>
struct build_indices<0> {
using type = indices<>;
};
template <std::size_t N>
using BuildIndices = typename build_indices<N>::type;
template <typename Iterator>
using ValueType = typename std::iterator_traits<Iterator>::value_type;
// internal overload with indices tag
template <std::size_t... I, typename RandomAccessIterator,
typename Array = std::array<ValueType<RandomAccessIterator>, sizeof...(I)>>
Array make_array(RandomAccessIterator first, indices<I...>) {
return Array { { first[I]... } };
}
// externally visible interface
template <std::size_t N, typename RandomAccessIterator>
std::array<ValueType<RandomAccessIterator>, N>
make_array(RandomAccessIterator first, RandomAccessIterator last) {
// last is not relevant if we're assuming the size is N
// I'll assert it is correct anyway
assert(last - first == N);
return make_array(first, BuildIndices<N> {});
}
// usage
auto a = make_array<N>(v.begin(), v.end());
này giả định một trình biên dịch có khả năng eliding bản sao trung gian. Tôi nghĩ rằng giả định không phải là một căng lớn.
Thực tế, nó có thể được thực hiện với các trình lặp đầu vào, vì việc tính toán từng phần tử trong một danh sách-init-braced được sắp xếp trước khi tính toán phần tử tiếp theo (§8.5.4/4).
// internal overload with indices tag
template <std::size_t... I, typename InputIterator,
typename Array = std::array<ValueType<InputIterator>, sizeof...(I)>>
Array make_array(InputIterator first, indices<I...>) {
return Array { { (void(I), *first++)... } };
}
Kể từ *first++
không có bất kỳ I
trong nó, chúng ta cần một hình nộm I
khiêu khích việc mở rộng gói. Toán tử dấu phẩy để giải cứu, với void()
để tắt tiếng cảnh báo về việc thiếu hiệu ứng và cũng ngăn ngừa các dấu phẩy quá tải.
Nguồn
2012-06-07 10:33:27
Có lý do nào cho tùy chọn đó không? Hiệu suất sẽ gần như chính xác như nhau bởi vì hàm tạo mặc định (thường) chỉ phân bổ các cấu trúc cơ bản mà bạn cần. Sẽ không có phân bổ, sao chép hoặc giải phóng thêm. –
@DavidSchwartz: Có lẽ tôi có một thành viên mảng const trong lớp của tôi và vì vậy tôi cần phải khởi tạo nó trong danh sách initializer chứ không phải là cơ quan constructor? – HighCommander4
--- Chúng ta có thể giới hạn bản thân với các trình vòng lặp truy cập ngẫu nhiên không? Nếu vậy, tôi có một số loại giải pháp --- Nevermind, không có cách nào để có được * kích thước * tại thời gian biên dịch. –