A recursive_transform для std :: array с различным типом возвращаемого значения
Это дополнительный вопрос для A recursive_transform для std :: vector с различным типом возврата . Спасибо Г. Слипену за дальнейшие предложения по обзору. Покопавшись в теме достижения более общей recursive_transformфункции как для различных типов вывода, так и для различных типов контейнеров, у меня все еще нет простого решения. Однако, основываясь на ответе Г. Sliepen в , в случае с std::vector, std::dequeи std::listтипы контейнеров могут быть решены. Я пытаюсь реализовать дополнительную recursive_transformфункцию перегрузки для std::array. Вот моя реализация.
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;
}
Тестовый пример 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;
Вот ссылка Godbolt . Код в этой ссылке, включая тестовые примеры для std::vector, std::dequeи std::list.
Все предложения приветствуются.
Сводная информация:
На какой вопрос это продолжение?
Recursive_transform для std :: vector с различным типом возврата
Какие изменения были внесены в код с момента последнего вопроса?
Тип обрабатываемого контейнера в предыдущей версии
recursive_transformфункции -std:vector. С ответом Г. Слипена этот список обрабатываемых типов контейнеров расширен доstd::vector,std::dequeиstd::list. Тогда я пытаюсь разобратьсяstd::arrayздесь.Почему запрашивается новый обзор?
В этой версии
recursive_transformфункции, похоже, она хорошо работает в упомянутом тестовом примереstd::array<int, 10> -> std::array<std::string, 10>. Однако есть некоторые проблемы, когда дело доходит до более сложного случая, такого какstd::array<std::array<int, 10>, 10> -> std::array<std::array<std::string, 10>, 10>(масштабируемость должна быть улучшена!). Если есть какие-либо предложения или возможные идеи по этому поводу, сообщите мне.
Ответы
Убедитесь, что вы проходите по constссылке последовательно
Основная проблема с вашим кодом заключалась в том, что вы не заставляли std::arrayперегрузку принимать входные данные по constссылке:
auto recursive_transform(std::array<T, S>& input, const F& f)
Просто добавь const! См. Эту ссылку Godboltstd::array с работой вложенных s.
Предпочитаю использовать std::begin()иstd::end()
На самом деле не имеет значения, хотите ли вы поддерживать только контейнеры из стандартной библиотеки, но при написании шаблонов предпочитайте использовать std::begin()и std::end()вместо ->begin()и ->end(). Преимущество заключается в том, что если вы используете нестандартный контейнер где - то , что не обеспечивает begin()и end()функции членов, она все равно будет возможно перегружать вне класса std::begin()и std::end()функций , чтобы добавить поддержку итератора к этому классу. Если вы используете его в своих шаблонах алгоритмов, ваши алгоритмы также будут поддерживать эти нестандартные классы.