Un recursive_transform per std :: array con vari tipi di ritorno
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 astd::vector,std::dequeestd::list. Quindi, sto cercando di affrontarestd::arrayqui.Perché viene richiesta una nuova recensione?
In questa versione della
recursive_transformfunzione, sembra che funzioni bene nel caso di test menzionatostd::array<int, 10> -> std::array<std::string, 10>. Tuttavia, ci sono alcuni problemi quando si tratta di casi più complessi comestd::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
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.