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