Search code examples
c++lambdac++20stdarray

Use std::array in function using 'overloaded' lambdas


I wish to do the following in C++20:

template <class... Ts>
struct overloaded : Ts... {
    using Ts::operator( )...;
};

// Updated to work with C++17
#if (_cplusplus != 202002L)    // check for C++17 or C++20
// Deduction guide, google `CTAD for aggregates` for more info
template <typename... Ts>
overloaded(Ts...) -> overloaded<Ts...>;    // not needed before C++20
#endif

template <typename T, long int C = 0>
void emit(T const& data) {

    auto emit = overloaded {

        [&](const auto& value) {
            mOs << value;
        },
        [&](const uint8_t& value) {
            mOs << std::showbase << (uint16_t)value;
        },
        [&](const std::array<T, C>& value) {
           for (auto& v : value) { // error: can't increment 0 size std::array
               mOs << v;
           }
        },
        // bunch more lambdas
    };
    emit(data);
}

// invoked by
emit(1);

How can the std::array be captured since the count is required?

Without setting C to zero all the other lambdas fail.

May not be possible but thought I'd ask.


Solution

  • You can use the lambdas template parameter list introduced in C++20. The lambdas argument is not a std::array<T,C> but it is T, and T is some std::array<S,C>:

    #include <iostream>
    #include <array>
    
    template <class... Ts>
    struct overloaded : Ts... {
        using Ts::operator( )...;
    };
    
    template <typename T>
    void emit(T const& data) {
        std::ostream& mOs = std::cout;
    
        auto emit = overloaded {
            [&](const auto& value) {
                mOs << value;
            },
            [&](const uint8_t& value) {
                mOs << std::showbase << (uint16_t)value;
            },
            [&]<typename S,size_t C>(const std::array<S, C>& value) {
               for (auto& v : value) { 
                   mOs << v;
               }
            },
            // bunch more lambdas
        };
        emit(data);
    }
    int main(){
        // invoked by
        std::array<int,42> x;
        emit(x);
    }
    

    Live Demo