Eine rekursive_Transform für std :: array mit verschiedenen Rückgabetypen

Oct 26 2020

Dies ist eine Folgefrage für A recursive_transform für std :: vector mit verschiedenen Rückgabetypen . Dank G. Sliepen geben Sie weitere Überprüfungsvorschläge. Nachdem recursive_transformich mich mit dem Thema befasst habe, eine allgemeinere Funktion sowohl für verschiedene Ausgabetypen als auch für verschiedene Containertypen zu erreichen, habe ich immer noch keine einfache Lösung. Allerdings basiert auf G. SLIEPEN Antwort , bei der std::vector, std::dequeund std::listContainertypen gelöst werden kann. Ich versuche zusätzlich eine weitere Überlastfunktion recursive_transformfür zu implementieren std::array. Hier ist meine Implementierung.

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

Der Testfall von 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;

Hier ist der Godbolt-Link . Der Code in diesem Link einschließlich der Testfälle für std::vector, std::dequeund std::list.

Alle Vorschläge sind willkommen.

Die zusammenfassenden Informationen:

  • Welcher Frage folgt es?

    Eine rekursive Transformation für std :: vector mit verschiedenen Rückgabetypen

  • Welche Änderungen wurden seit der letzten Frage am Code vorgenommen?

    Der handhabbare Containertyp in der vorherigen recursive_transformFunktionsversion ist std:vector. Mit G. SLIEPEN Antwort , diese handhabbar Containertyp - Liste wird erweitert std::vector, std::dequeund std::list. Dann versuche ich std::arrayhier umzugehen .

  • Warum wird nach einer neuen Bewertung gefragt?

    In dieser recursive_transformFunktionsversion scheint es, dass es im genannten Testfall gut funktioniert std::array<int, 10> -> std::array<std::string, 10>. Es gibt jedoch einige Probleme, wenn es um den komplexeren Fall geht, wie std::array<std::array<int, 10>, 10> -> std::array<std::array<std::string, 10>, 10>(die Skalierbarkeit muss verbessert werden!). Wenn es einen Vorschlag oder eine mögliche Idee dazu gibt, lassen Sie es mich bitte wissen.

Antworten

1 G.Sliepen Oct 26 2020 at 20:37

Stellen Sie sicher, dass Sie als constReferenz konsistent übergeben

Das Hauptproblem mit Ihrem Code war, dass Sie die std::arrayÜberladung nicht dazu gebracht haben , die Eingabe als constReferenz zu verwenden:

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

Einfach hinzufügen const! Sehen Sie diesen Godbolt-Link mit der std::arrayArbeit der verschachtelten s.

Verwenden Sie lieber std::begin()undstd::end()

Es spielt keine Rolle, ob Sie nur Container aus der Standardbibliothek unterstützen möchten, aber beim Schreiben von Vorlagen bevorzugen Sie die Verwendung von std::begin()und std::end()anstelle von ->begin()und ->end(). Der Vorteil besteht darin , dass , wenn Sie einen Nicht-Standard - Container irgendwo verwenden , das nicht bieten begin()und end()Funktionen Mitglied, wird es noch möglich sein , die out-of-Klasse zu überlasten std::begin()und std::end()Funktionen Iterator Unterstützung dieser Klasse hinzuzufügen. Wenn Sie es in Ihren Algorithmusvorlagen verwenden, unterstützen Ihre Algorithmen auch diese nicht standardmäßigen Klassen.