Confusing templates in C++17 example of std::visit

  • A+
Category:Languages

When looking at std::visit() page in cppreference, https://en.cppreference.com/w/cpp/utility/variant/visit, I encountered the code I can't make sense of...

Here's the abbreviated version:

#include <iomanip> #include <iostream> #include <string> #include <type_traits> #include <variant> #include <vector>  using var_t = std::variant<int, long, double, std::string>;  template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; template<class... Ts> overloaded(Ts...)->overloaded<Ts...>;  int main() {     std::vector<var_t> vec = { 10, 15l, 1.5, "hello" };     for (auto& v : vec) {         std::visit(overloaded{             [](auto arg) { std::cout << arg << ' '; },             [](double arg) { std::cout << std::fixed << arg << ' '; },             [](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },             }, v);     } } 

What are the two lines declaring overloaded, just above int main(), mean?

Thank you for explaining!

 


What are the two lines declaring overloaded, just above int main(), mean?

The first one

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

is a classic class/struct declaration/definition/implementation. Valid from C++11 (because use variadic templates).

In this case, overload inherit from all template parameters and enable (using row) all inherited operator().

Unfortunately the variadic using is available only starting from C++17.

The second one

template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; 

is a "deduction guide" (see this page for more details) and it's a new C++17 feature.

In your case, the deduction guide say that when you write something as

auto ov = overloaded{ arg1, arg2, arg3, arg4 }; 

or also

overloaded ov{ arg1, args, arg3, arg4 }; 

ov become a overloaded<decltype(arg1), decltype(arg2), decltype(arg3), decltype(arg4)>

This permit you to write something as

 overloaded{             [](auto arg) { std::cout << arg << ' '; },             [](double arg) { std::cout << std::fixed << arg << ' '; },             [](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },             } 

that in C++14 was

auto l1 = [](auto arg) { std::cout << arg << ' '; }; auto l2 = [](double arg) { std::cout << std::fixed << arg << ' '; }; auto l3 = [](const std::string& arg) { std::cout << std::quoted(arg) << ' '; }  overloaded<decltype(l1), decltype(l2), decltype(l3)> ov{l1, l2, l3}; 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: