Um recursive_transform para std :: array com vários tipos de retorno

Oct 26 2020

Esta é uma questão de acompanhamento para A recursive_transform para std :: vector com vários tipos de retorno . Agradecimentos a G. Sliepen fornecer sugestões de revisão adicionais. Depois de me aprofundar no tópico de alcançar uma recursive_transformfunção mais genérica em vários tipos de saída e vários tipos de contêiner, ainda não tenho uma solução simples. No entanto, com base na resposta de G. Sliepen , caso do std::vector, std::dequee std::listtipos de recipiente pode ser resolvido. Estou tentando implementar outra recursive_transformfunção de sobrecarga adicional para std::array. Aqui está minha implementação.

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;
}

O caso de teste de 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;

Aqui está o link Godbolt . O código neste link, incluindo os casos de teste para std::vector, std::dequee std::list.

Todas as sugestões são bem-vindas.

As informações resumidas:

  • Para qual pergunta é um seguimento?

    Um recursive_transform para std :: vector com vários tipos de retorno

  • Que mudanças foram feitas no código desde a última pergunta?

    O tipo de contêiner manipulável na versão anterior da recursive_transformfunção é std:vector. Com a resposta de G. Sliepen , esta lista de tipos de contêiner manipuláveis é estendida para std::vector, std::dequee std::list. Então, estou tentando lidar com isso std::arrayaqui.

  • Por que uma nova revisão está sendo solicitada?

    Nesta versão de recursive_transformfunção, parece que está funcionando bem no caso de teste mencionado std::array<int, 10> -> std::array<std::string, 10>. No entanto, existem alguns problemas quando se trata de casos mais complexos como std::array<std::array<int, 10>, 10> -> std::array<std::array<std::string, 10>, 10>(a escalabilidade a ser melhorada!) Se houver alguma sugestão ou possível ideia sobre isso, por favor me avise.

Respostas

1 G.Sliepen Oct 26 2020 at 20:37

Certifique-se de passar por constreferência de forma consistente

O principal problema com o seu código é que você não fez a std::arraysobrecarga tomar a entrada por constreferência:

auto recursive_transform(std::array<T, S>& input, const F& f)

Basta adicionar const! Veja este link Godbolt com o std::arrayfuncionamento dos aninhados .

Prefiro usar std::begin()estd::end()

Realmente não importa se você deseja apenas oferecer suporte a containers da biblioteca padrão, mas ao escrever modelos, prefira usar std::begin()e em std::end()vez de ->begin()e ->end(). A vantagem é que se você estiver usando um algum lugar recipiente não-padrão que não fornece begin()e end()funções membro, ainda será possível sobrecarregar o out-of-classe std::begin()e std::end()funções para adicionar iterador apoio a essa classe. Se você usá-lo em seus modelos de algoritmos, seus algoritmos também oferecerão suporte a essas classes não padrão.