2
\$\begingroup\$

This is a follow-up question for A recursive_transform for std::vector with various return type. Thanks to G. Sliepen provide further review suggestions. After digging into the topic of achieving a more generic recursive_transform function in both various output type and various container type, I still have no simple solution. However, based on G. Sliepen's answer, the case of the std::vector, std::deque and std::list container types may be resolved. I am trying to implement additional another overload recursive_transform function for std::array. Here's my implementation.

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

The test case of 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;

Here's the Godbolt link. The code in this link including the test cases for std::vector, std::deque and std::list.

All suggestions are welcome.

The summary information:

  • Which question it is a follow-up to?

    A recursive_transform for std::vector with various return type

  • What changes has been made in the code since last question?

    The handleable container type in the previous version of recursive_transform function is std:vector. With G. Sliepen's answer, this handleable container type list is extended to std::vector, std::deque and std::list. Then, I am trying to deal with std::array here.

  • Why a new review is being asked for?

    In this version of recursive_transform function, it seems that working well in the mentioned test case std::array<int, 10> -> std::array<std::string, 10>. However, there is some issues when it comes to the more complex case like std::array<std::array<int, 10>, 10> -> std::array<std::array<std::string, 10>, 10> (the scalability to be improved!) If there is any suggestion or possible idea about this, please let me know.

\$\endgroup\$
1
\$\begingroup\$

Ensure you pass by const reference consistently

The main problem with your code was that you didn't make the std::array overload take the input by const reference:

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

Just add const! See this Godbolt link with the nested std::arrays working.

Prefer using std::begin() and std::end()

It doesn't really matter if you only want to support containers from the standard library, but when writing templates, prefer using std::begin() and std::end() instead of ->begin() and ->end(). The advantage is that if you are using a non-standard container somewhere that doesn't provide begin() and end() member functions, it will still be possible to overload the out-of-class std::begin() and std::end() functions to add iterator support to that class. If you use it in your algorithm templates, then your algorithms will also support those non-standard classes.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.