Recursive_transform for std :: array z różnymi typami zwracania

Oct 26 2020

To jest pytanie uzupełniające dla A recursive_transform for std :: vector z różnymi typami zwracania . Dzięki G. Sliepen przedstawię dalsze sugestie dotyczące recenzji. Po zagłębieniu się w temat uzyskania bardziej ogólnej recursive_transformfunkcji zarówno w różnych typach wyjścia, jak i różnych typach kontenerów, nadal nie mam prostego rozwiązania. Jednak na podstawie odpowiedzi G. Sliepen jest , w przypadku osób std::vector, std::dequea std::listrodzaje kontenerów mogą być rozwiązane. Próbuję zaimplementować dodatkową inną recursive_transformfunkcję przeciążenia dla std::array. Oto moja realizacja.

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

Przypadek testowy 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;

Oto łącze Godbolt . Kod w tym linku w tym przypadków testowych dla std::vector, std::dequei std::list.

Wszelkie sugestie są mile widziane.

Podsumowanie informacji:

  • Które pytanie jest kontynuacją?

    Recursive_transform for std :: vector z różnymi typami zwracania

  • Jakie zmiany wprowadzono w kodzie od ostatniego pytania?

    Obsługiwany typ kontenera w poprzedniej wersji recursive_transformfunkcji to std:vector. Z odpowiedzi G. Sliepen za ten rodzaj manipulowania lista pojemnik rozszerza się std::vector, std::dequea std::list. Następnie próbuję sobie z std::arraytym poradzić .

  • Dlaczego prosi się o nową recenzję?

    W tej wersji recursive_transformfunkcji wygląda na to, że działa dobrze we wspomnianym przypadku testowym std::array<int, 10> -> std::array<std::string, 10>. Jednak są pewne problemy, jeśli chodzi o bardziej złożone przypadki, takie jak std::array<std::array<int, 10>, 10> -> std::array<std::array<std::string, 10>, 10>(skalowalność do poprawy!). Jeśli są jakieś sugestie lub możliwy pomysł na ten temat, daj mi znać.

Odpowiedzi

1 G.Sliepen Oct 26 2020 at 20:37

Upewnij się, że constkonsekwentnie przekazujesz referencje

Główny problem z twoim kodem polegał na tym, że std::arrayprzeciążenie nie pobierało danych wejściowych przez constodniesienie:

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

Po prostu dodaj const! Zobacz to łącze Godbolt z std::arraydziałającymi gniazdami .

Wolisz używać std::begin()istd::end()

Nie ma znaczenia, czy chcesz obsługiwać tylko kontenery z biblioteki standardowej, ale pisząc szablony, wolisz używać std::begin()i std::end()zamiast ->begin()i ->end(). Zaletą jest to, że jeśli używasz niestandardowego kontenera gdzieś, który nie zapewnia begin()i end()funkcji składowych, nadal będzie możliwe przeciążenie nie-klasy std::begin()i std::end()funkcji, aby dodać obsługę iteratora do tej klasy. Jeśli użyjesz go w swoich szablonach algorytmów, twoje algorytmy będą również obsługiwać te niestandardowe klasy.