A recursive_transform для std :: array с различным типом возвращаемого значения

Oct 26 2020

Это дополнительный вопрос для 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>(масштабируемость должна быть улучшена!). Если есть какие-либо предложения или возможные идеи по этому поводу, сообщите мне.

Ответы

1 G.Sliepen Oct 26 2020 at 20:37

Убедитесь, что вы проходите по 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()функций , чтобы добавить поддержку итератора к этому классу. Если вы используете его в своих шаблонах алгоритмов, ваши алгоритмы также будут поддерживать эти нестандартные классы.