Как вызвать std :: visit внутри лямбды с посетителем, который является функциональным объектом, захваченным по значению - PullRequest
1 голос
/ 04 марта 2020

Кажется, что нелегко вызвать std::visit внутри лямбды, используя посетителя, который является функциональным объектом, захваченным значением. Захват по ссылке работает нормально, хотя. Почему это так и возможно ли это как-то сделать?

Я не понимаю сообщение об ошибке компиляции в этом случае от MSV C 2017:

std :: visit ': не найдено соответствующей перегруженной функции
Не удалось шаблон специализированной функции неизвестного типа std :: visit (_Callable &&, _ Variants && ...)

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

Код, иллюстрирующий проблему:

#include <variant>

struct T {
    void operator()(int i) {};
    void operator()(float f) {};
};

int main()
{
    std::variant<int, float> v = 1;
    T t;

    // Does not compile.
    //auto l1 = [t](auto v) { std::visit(t, v); };
    //l1(v);

    // Compiles.
    auto l2 = [&t](auto v) { std::visit(t, v); };
    l2(v);

    // Compiles.
    std::visit(t, v);

}

1 Ответ

5 голосов
/ 04 марта 2020

Оператор вызова, сгенерированный лямбда-выражением, помечается как const, так как при использовании метода const все члены этого элемента также помечаются как const. Так как операторы вызова T не помечены как const, вы не можете вызывать их из лямбды. Он работает для лямбды, которая захватывает по ссылке, потому что const не распространяется с указателями и элементами ссылочных данных.

Таким образом, чтобы разрешить ее, вы можете пометить лямбда-переменную, которая сделает оператор вызова не константным, захват по ссылке как вы делаете, или пометьте операторы вызова T const.

...