Ender
Ender

Reputation: 1778

How to pass a second parameter in overload to std::visit?

I'm trying to pass a std::shared_ptr<std::jthread> as a parameter in this lambda, but getting an error with this std::visit. It works fine if I leave out the second parameter in the overload.

The error can be seen here. https://coliru.stacked-crooked.com/a/95b62272fa49335d

#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <variant>

template<class... Ts>
struct overload : Ts... {
    using Ts::operator()...;
};

template<class... Ts>
overload(Ts...) -> overload<Ts...>;

class ObjA {
    int a;
};

class ObjB {
    int b;
};

int main()
{
    ObjA a;

    std::variant<ObjA, ObjB> v;

    v = a;

    int rc { 0 };// unused here

    std::shared_ptr<std::jthread> sp = nullptr;

    std::visit(overload {
        [&rc](ObjA& objA, std::shared_ptr<std::jthread> thr) {
            std::cout << "ObjA!\n";        
        },
        [&rc](ObjB& objB, std::shared_ptr<std::jthread> thr) {
            std::cout << "ObjB!\n";
        }
    }, v);

    return 0;
}

Upvotes: 1

Views: 2033

Answers (1)

Brian Bi
Brian Bi

Reputation: 119641

You've passed a callable to std::visit that accepts two arguments. However, the number of arguments of the callable has to match the number of variants provided to std::visit. That is, std::visit(c, v) will only compile if c takes one argument, and std::visit(c, v1, v2) will only compile if c takes two arguments, and so on. This is because std::visit works by calling c with one argument for each variant, whose type is the type currently contained in the corresponding variant.

I'm not sure exactly what you're trying to do in your code, since in your example, most of the variables are unused. Perhaps your problem can be solved by capturing a std::shared_ptr<std::jthread> object in the lambdas, so that only one argument (the ObjA&/ObjB&) needs to be passed to the call operator.

Upvotes: 2

Related Questions