Một recursive_transform cho std :: array với nhiều kiểu trả về
Đây là một câu hỏi tiếp theo cho A recursive_transform cho std :: vector với nhiều kiểu trả về khác nhau . Cảm ơn G. Sliepen cung cấp thêm các đề xuất đánh giá. Sau khi đào sâu vào chủ đề để đạt được một recursive_transformchức năng chung hơn ở cả loại đầu ra khác nhau và loại thùng chứa khác nhau, tôi vẫn không có giải pháp đơn giản nào. Tuy nhiên, dựa trên câu trả lời của G. Sliepen , trường hợp của std::vector, std::dequevà std::listcác loại container có thể được giải quyết. Tôi đang cố gắng triển khai bổ sung một recursive_transformhàm quá tải khác cho std::array. Đây là cách thực hiện của tôi.
template<class T, std::size_t S, class F>
auto recursive_transform(std::array<T, S>& input, const F& f)
{
using TransformedValueType = decltype(recursive_transform(*input.cbegin(), f));
std::array<TransformedValueType, S> output;
std::transform(input.cbegin(), input.cend(), output.begin(),
[f](auto& element)
{
return recursive_transform(element, f);
}
);
return output;
}
Trường hợp thử nghiệm của std::array:
// std::array<int, 10> -> std::array<std::string, 10>
std::array<int, 10> test_array;
for (int i = 0; i < 10; i++)
{
test_array[i] = 1;
}
auto recursive_transform_result5 = recursive_transform(
test_array,
[](int x)->std::string { return std::to_string(x); }); // For testing
std::cout << "string: " + recursive_transform_result5.at(0) << std::endl;
Đây là liên kết Godbolt . Các mã trong liên kết này bao gồm cả các trường hợp thử nghiệm cho std::vector, std::dequevà std::list.
Tất cả các đề xuất đều được chào đón.
Thông tin tóm tắt:
Câu hỏi nào là tiếp theo?
Một recursive_transform cho std :: vector với nhiều kiểu trả về
Những thay đổi nào đã được thực hiện trong mã kể từ câu hỏi trước?
Loại vùng chứa có thể xử lý trong phiên bản trước của
recursive_transformchức năng làstd:vector. Với câu trả lời của G. Sliepen , danh sách loại vùng chứa có thể xử lý này được mở rộng thànhstd::vector,std::dequevàstd::list. Sau đó, tôi đang cố gắng giải quyếtstd::arrayở đây.Tại sao một đánh giá mới lại được yêu cầu?
Trong phiên bản
recursive_transformchức năng này, có vẻ như hoạt động tốt trong trường hợp thử nghiệm đã đề cậpstd::array<int, 10> -> std::array<std::string, 10>. Tuy nhiên, có một số vấn đề khi nói đến trường hợp phức tạp hơn nhưstd::array<std::array<int, 10>, 10> -> std::array<std::array<std::string, 10>, 10>(khả năng mở rộng được cải thiện!) Nếu có bất kỳ đề xuất hoặc ý tưởng khả thi nào về điều này, vui lòng cho tôi biết.
Trả lời
Đảm bảo bạn chuyển qua consttham chiếu một cách nhất quán
Vấn đề chính với mã của bạn là bạn đã không thực hiện std::arrayquá tải lấy đầu vào bằng cách consttham chiếu:
auto recursive_transform(std::array<T, S>& input, const F& f)
Chỉ cần thêm const! Xem liên kết Godbolt này với các nút lồng nhau std::arrayđang hoạt động.
Thích sử dụng std::begin()vàstd::end()
Không thực sự quan trọng nếu bạn chỉ muốn hỗ trợ các vùng chứa từ thư viện tiêu chuẩn, nhưng khi viết các mẫu, hãy thích sử dụng std::begin()và std::end()thay vì ->begin()và ->end(). Ưu điểm là nếu bạn đang sử dụng một vùng chứa không chuẩn ở một nơi nào đó không cung cấp begin()và các end()hàm thành viên, vẫn có thể quá tải các hàm ngoài lớp std::begin()và các std::end()hàm để thêm hỗ trợ trình vòng lặp vào lớp đó. Nếu bạn sử dụng nó trong các mẫu thuật toán của mình, thì các thuật toán của bạn cũng sẽ hỗ trợ các lớp không chuẩn đó.