это действительно сложно и довольно сложно, так как в игру вступает множество мощных хитростей мета-программирования. Этот ответ может охватывать только верхушку айсберга :-)
трю наstd:variant/std::visit
Док здесь:http://en.cppreference.com/w/cpp/utility/variant/visit а также погуглил много, пытаясь понять магию позадиstd::visit
а такжеstd::variant
.
Итак, мой вопрос заключается в следующем. В приведенном примере оба вполиморфная лямбда и "перегружен" происходит некоторое "волшебство", которое позволяет извлечь правильный тип изstd::variant
.
Итак, глядя на это:
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);
}
Для каждогоv
, это просто вариант, как вызывается правильная перегруженная лямбда-функция? Кажется, есть некоторая логика, которая должна выяснить точный типstd::variant
бросьте его и отправьте в нужное место. У меня вопрос как это работает? То же самое для этого:
std::visit([](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>)
std::cout << "int with value " << arg << '\n';
else if constexpr (std::is_same_v<T, long>)
std::cout << "long with value " << arg << '\n';
else if constexpr (std::is_same_v<T, double>)
std::cout << "double with value " << arg << '\n';
else if constexpr (std::is_same_v<T, std::string>)
std::cout << "std::string with value " << std::quoted(arg) << '\n';
else
static_assert(always_false<T>::value, "non-exhaustive visitor!");
}, w);
Мы передаем полиморфную лямбду посетителю как вызываемый объект иw
это какой-то вариант, который может содержать int, long, double или std :: string. Где логика, которая выясняет правильный тип такusing T = std::decay_t<decltype(arg)>;
получить фактический тип конкретного экземпляра варианта?