Так этот пример от: http://en.cppreference.com/w/cpp/utility/variant/visit объявляет специализированный тип:
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
Который построен здесь как r-значение:
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);
Я пытаюсь понять, как это работает. Какого типа это overloaded
наследует отсюда? Это похоже на массив лямбд, но я не вижу, как это operator()
, Может кто-нибудь объяснить, как здесь работает наследство?
overloaded
наследуется от каждой лямбды индивидуально, и у каждой лямбды есть оператор вызова. Поэтому вы создаете структуру, в которой все операторы вызова находятся в одном наборе перегрузки. Пока они не являются двусмысленными, правильный будет автоматически выбран.
Вы можете представить себе шаблон вариации для расширения до
struct overloaded :
// inherits from
decltype([](auto arg) { std::cout << arg << ' '; }),
decltype([](double arg) { std::cout << std::fixed << arg << ' '; }),
decltype([](const std::string& arg) { std::cout << std::quoted(arg) << ' '; })
// has three operator()s
{
using decltype([](auto arg) { std::cout << arg << ' '; })::operator();
using decltype([](double arg) { std::cout << std::fixed << arg << ' '; })::operator();
using decltype([](const std::string& arg) { std::cout << std::quoted(arg) << ' '; })::operator();
};
За исключением реального кода, это не сработает, потому что лямбды с одинаковым телом все равно будут иметь разные типы.
Это создает 1 overloaded
тип с множественным наследованием для каждого экземпляра.
Других решений пока нет …