Un recursive_transform per std :: array con vari tipi di ritorno

Oct 26 2020

Questa è una domanda di follow-up per A recursive_transform per std :: vector con vari tipi di ritorno . Grazie a G. Sliepen fornire ulteriori suggerimenti di revisione. Dopo aver approfondito l'argomento per ottenere una recursive_transformfunzione più generica sia in vari tipi di output che in vari tipi di contenitore, non ho ancora una soluzione semplice. Tuttavia, sulla base di risposta di G. Sliepen , il caso del std::vector, std::dequee std::listtipi di contenitori possono essere risolti. Sto cercando di implementare un'altra recursive_transformfunzione di sovraccarico aggiuntiva per std::array. Ecco la mia implementazione.

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

Il caso di prova di 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;

Ecco il link Godbolt . Il codice in questo link inclusi i casi di test per std::vector, std::dequee std::list.

Tutti i suggerimenti sono ben accetti.

Le informazioni di sintesi:

  • A quale domanda è un follow-up?

    Un recursive_transform per std :: vector con vari tipi di ritorno

  • Quali modifiche sono state apportate al codice dall'ultima domanda?

    Il tipo di contenitore gestibile nella versione precedente della recursive_transformfunzione è std:vector. Con la risposta di G. Sliepen , questo elenco di tipi di contenitori gestibili viene esteso a std::vector, std::dequee std::list. Quindi, sto cercando di affrontare std::arrayqui.

  • Perché viene richiesta una nuova recensione?

    In questa versione della recursive_transformfunzione, sembra che funzioni bene nel caso di test menzionato std::array<int, 10> -> std::array<std::string, 10>. Tuttavia, ci sono alcuni problemi quando si tratta di casi più complessi come std::array<std::array<int, 10>, 10> -> std::array<std::array<std::string, 10>, 10>(la scalabilità da migliorare!) Se c'è qualche suggerimento o possibile idea su questo, per favore fatemelo sapere.

Risposte

1 G.Sliepen Oct 26 2020 at 20:37

Assicurati di passare per constriferimento in modo coerente

Il problema principale con il tuo codice era che non hai fatto in modo che il std::arraysovraccarico prendesse l'input per constriferimento:

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

Basta aggiungere const! Vedi questo collegamento Godbolt con il std::arrayfunzionamento degli annidati .

Preferisco usare std::begin()estd::end()

Non importa se vuoi supportare solo i contenitori dalla libreria standard, ma quando scrivi modelli, preferisci usare std::begin()e std::end()invece di ->begin()e ->end(). Il vantaggio è che se si sta utilizzando un qualche contenitore non standard che non fornisce begin()e end()funzioni membro, sarà ancora possibile sovraccaricare l'out-of-class std::begin()e di std::end()funzioni per aggiungere iteratore sostegno a tale classe. Se lo usi nei tuoi modelli di algoritmo, i tuoi algoritmi supporteranno anche quelle classi non standard.