Получение активного значения в std :: visit, не зная, какое значение активно - PullRequest
0 голосов
/ 14 февраля 2019

Я хочу получить активное значение в std :: варианте, не зная, какое из них активно.Я думал, что мог бы написать шаблон посетителя и использовать std :: visit, но это не работает.

#include <variant>
#include <string>
#include <iostream>

struct Visit_configuration {
    template<typename Data_type>
    Data_type operator()(Data_type& t) const
    {
        return t;
    }
};

int main()
{
    std::variant<int, std::string> v;
    v = "hello";

    std::cout << std::visit(Visit_configuration(), v);   // expect "hello"
    std::cin.get();
}

MSVC не компилируется и выдает:

ошибка C2338:Для посещения () требуется, чтобы результат всех потенциальных вызовов имел одинаковый тип и категорию значений (N4741 23.7.7 [option.visit] / 2).

примечание: см. ссылку на создание экземпляра шаблона функции 'int std:: visit &, 0> (_ Callable &&, std :: option &) 'компилируется

Так как это исправить?

edit: я хочу использовать полученное значение, может быть, такжедля других, поэтому вставка cout в шаблон не то, что я ищу.

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Задайте себе вопрос:
Какой тип возврата std::visit, если вы не знаете, какая часть variant активна?

То естьвопрос, на который компилятор должен ответить.И ответ не может быть «это зависит» - вы (как, например, компилятор) должны выбрать ровно один тип во время компиляции.Вызов visit не может возвращать различные типы во время выполнения.

Если вы хотите работать с различными типами "во время выполнения", вы должны быть в функции, настроенной на тип, с которым хотите работать.Другими словами, должны быть разными функциями (или экземплярами шаблонов функций) для обработки случаев «записать int в cout» и «записать строку в cout».Вы не можете сделать это в той же (не шаблонной) функции.

Простое решение здесь, таким образом, заключается в том, чтобы поместить std::cout << в вашу шаблонную функцию посетителя - вот в чем смысл посещения: указание того, что должно произойтив каждом случае.

Если вы хотите «использовать полученное значение, возможно, также для [некоторой] другой [цели]», тогда эта «другая цель» также должна быть частью / a посетителя.Только тогда вы можете иметь эту «другую цель» обрабатывать разные случаи одновременно (например, в шаблонной функции).В противном случае вы должны решить уже во время компиляции, какой тип будет использоваться - компилятор не собирается оставлять этот выбор открытым на более позднее время (время выполнения).

0 голосов
/ 14 февраля 2019

Возвращаемый тип функции посетителя должен быть идентичным.

Вместо этого создайте посетителя принтера:

struct PrinterVisitor {
    template<typename T>
    void operator()(const T& t) const
    {
        std::cout << t;
    }
};

int main()
{
    std::variant<int, std::string> v;
    v = "hello";

    std::visit(PrinterVisitor{}, v);   // expect "hello"
}

И в вашем случае вы даже можете иметь лямбду:

int main()
{
    std::variant<int, std::string> v;
    v = "hello";

    std::visit([](const auto& t){std::cout << t;}, v);   // expect "hello"
}
...