Un recursive_transform pour std :: array avec différents types de retour

Oct 26 2020

C'est une question de suivi pour A recursive_transform pour std :: vector avec différents types de retour . Merci à G. Sliepen de fournir d'autres suggestions d'examen. Après avoir creusé le sujet de la réalisation d'une recursive_transformfonction plus générique à la fois dans divers types de sortie et divers types de conteneurs, je n'ai toujours pas de solution simple. Cependant, sur la base de la réponse de G. Sliepen , le cas du std::vector, std::dequeet les std::listtypes de conteneurs peuvent être résolus. J'essaie d'implémenter une autre recursive_transformfonction de surcharge supplémentaire pour std::array. Voici ma mise en œuvre.

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

Le cas de test 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;

Voici le lien Godbolt . Le code de ce lien, y compris les cas de test pour std::vector, std::dequeet std::list.

Toutes les suggestions sont les bienvenues.

Les informations récapitulatives:

  • À quelle question fait-il suite?

    Un recursive_transform pour std :: vector avec différents types de retour

  • Quelles modifications ont été apportées au code depuis la dernière question?

    Le type de conteneur manipulable dans la version précédente de recursive_transformfunction est std:vector. Avec la réponse de G. Sliepen , cette liste de types de conteneurs gérables est étendue à std::vector, std::dequeet std::list. Ensuite, j'essaye de traiter std::arrayici.

  • Pourquoi un nouvel examen est-il demandé?

    Dans cette version de recursive_transformfonction, il semble que cela fonctionne bien dans le cas de test mentionné std::array<int, 10> -> std::array<std::string, 10>. Cependant, il y a quelques problèmes en ce qui concerne le cas plus complexe comme std::array<std::array<int, 10>, 10> -> std::array<std::array<std::string, 10>, 10>(l'évolutivité à améliorer!) S'il y a une suggestion ou une idée possible à ce sujet, veuillez me le faire savoir.

Réponses

1 G.Sliepen Oct 26 2020 at 20:37

Assurez-vous de passer par constréférence de manière cohérente

Le principal problème avec votre code était que vous n'avez pas fait en sorte que la std::arraysurcharge prenne l'entrée par constréférence:

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

Ajoutez simplement const! Voir ce lien Godbolt avec le travail imbriqué std::array.

Préférez utiliser std::begin()etstd::end()

Peu importe si vous souhaitez uniquement prendre en charge les conteneurs de la bibliothèque standard, mais lorsque vous écrivez des modèles, préférez utiliser std::begin()et std::end()au lieu de ->begin()et ->end(). L'avantage est que si vous utilisez un endroit conteneur non standard qui ne fournit pas begin()et les end()fonctions membres, il sera encore possible de surcharger le hors-classe std::begin()et les std::end()fonctions d'ajouter iterator soutien à cette classe. Si vous l'utilisez dans vos modèles d'algorithmes, vos algorithmes prendront également en charge ces classes non standard.