I'm trying to recreate a simple example from this article on the common "overloaded lambda" trick to create an overload set that can be used with std::visit
or other similar facilities. My simplified example is:
#include <iostream>
#include <vector>
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; // (1)
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; // (2)
int main() {
overloaded os(
[](int i) { std::cout << "int: " << i << std::endl; },
[](const char *str) { std::cout << "str: " << str << std::endl; }
);
os(1);
os("Hello world!");
return 0;
}
<source>: In function 'int main()':
<source>:12:5: error: no matching function for call to 'overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >::overloaded(main()::<lambda(int)>, main()::<lambda(const char*)>)'
12 | );
| ^
<source>:4:30: note: candidate: 'constexpr overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >::overloaded(const overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >&)'
4 | template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; // (1)
| ^~~~~~~~~~
<source>:4:30: note: candidate expects 1 argument, 2 provided
<source>:4:30: note: candidate: 'constexpr overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >::overloaded(overloaded<main()::<lambda(int)>, main()::<lambda(const char*)> >&&)'
<source>:4:30: note: candidate expects 1 argument, 2 provided
If I change the initialization of overloaded os
to use brace initialization, then it works. Can anyone explain the distinction here?