это действительно сложно и довольно сложно, так как в игру вступает множество мощных хитростей мета-программирования. Этот ответ может охватывать только верхушку айсберга :-)

трю на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)>; получить фактический тип конкретного экземпляра варианта?

 Casey24 дек. 2017 г., 00:19
 Kobi24 дек. 2017 г., 00:31
@ Кейси, спасибо. Похоже, index () и получить <I> является ответом на выше. спасибо за ссылку!
 cpplearner23 дек. 2017 г., 22:55
Вы просите о реализацииstd::visit?
 Kobi23 дек. 2017 г., 22:57
@cpplearner - наверное :)

Ответы на вопрос(1)

Решение Вопроса

std::visit создает массив указателей на функции (во время компиляции), который состоит из созданных экземпляров указателей на функции дляКаждый тип, Вариант хранит индекс типа времени выполненияi (встроенный номер), который позволяет выбрать правильныйi-я функция указатель и введите значение.

Вы можете задаться вопросом, как мы можем хранить указатели на функции с различными типами аргументов в массиве времени компиляции? -> Это делается с помощью стирания типа (я думаю), что означает, что можно хранить функции, например,void* аргумент, например&A<T>::call:

template<typename T>
static A
{
   static call(void*p) { otherFunction(static_cast<T*>(p)); } 
}

где каждыйcall отправляет к правильной функцииotherFunction с аргументом (это ваша лямбда в конце). Тип стирания означает функциюauto f = &A<T>::call не имеет больше понятия типаT и имеет подписьvoid(*)(void*).

std::variant это действительно сложно и довольно сложно, так как в игру вступает множество мощных хитростей мета-программирования. Этот ответ может охватывать только верхушку айсберга :-)

Ваш ответ на вопрос