2

Code:

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

struct ignore
{
    template <typename T>
    void operator()([[maybe_unused]]const T&)
    {
        std::cout << "other type" << std::endl;
    }
};

template <class... Ts>
struct overloaded_ignore : ignore, Ts...
{
    overloaded_ignore(Ts...) : ignore(){}
    using Ts::operator()...;
    using ignore::operator();
};

int main()
{
    std::variant<int,float,std::string> my_var = std::string("helloworld");
    // std::variant<int,float,std::string> my_var = 5.0F;
    // std::variant<int,float,std::string> my_var = 3;


    std::visit(overloaded_ignore{
        [](const int& t)
        {
            std::cout << "int var: " << t << std::endl;
        },
        [](const std::string& t)
        {
            std::cout << "string var: " << t << std::endl;
        }
        }, my_var);

    
    return 0;
}

I expect to output "string var: helloworld", but the "other type" is outputed.

How to fix this?

Note: the ignored operator() is required.

1 Answer 1

3

Just add the const-qualifier to ignore::operator() as the lambda's operator() is const-qualified by default:

struct ignore
{
    template <typename T>
    void operator()([[maybe_unused]]const T&) const // <--
    {
        std::cout << "other type" << std::endl;
    }
};

template <class... Ts>
struct overloaded_ignore : ignore, Ts...
{
    overloaded_ignore(Ts...) : ignore(){}
    using Ts::operator()...;
    using ignore::operator();
};

Demo

(Since overloaded_ignore{...} is a prvalue, this makes the non-const ignore::operator() a better match before)

Sign up to request clarification or add additional context in comments.

6 Comments

If you move the operator() to the overloaded_ignore, you can also save the constructor and one of the using ...: godbolt.org/z/nThvYaosr
it works. your really surprise me since you fix this issue by so easy way. thank you very much.
yes, actually at beginning i indeed leave the operator() in overloaded_ignore like you said but without const qualifier, so i can't get the correct output, so i move it to a new struct. i was thinking since the "Ts"(which is lambda in constructor argument list) is a fixed type, so it should be a better match than template<T> void ignore::operator()(auto&t); but it's not.
could you please explain why the ignore::operator() is a better match than lambda in my implementation, even the object of overloaded_ignore is a prvalue, but why compile choose ignore::operator() first? @JeJo
@anti-walker Because you are calling operator() of overloaded_ignore{...}, which is a prvalue value rather than a const object. If you create a const overloaded_ignore object, then the lambda will be a better match if you call its operator().
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.