Search code examples
c++friendvariant

My visitor class has private operator(), can I friend std::visit?


I need to std::visit a std::variant, but my visitor class has private operator(). Since my reviewers apparently do not like me making those public, can I friend std::visit?

I would also need it to be able to compile both in GCC and Clang, so the signature I would need to provide after the friend keyword need to work with both.

class Visitor
{
...
private:
    void operator()(TypeA&);
    void operator()(TypeB&);
...

friend ::std::visit // here is where I am not sure what to write
};

Solution

  • As it is implementation-defined, where exactly the functor is actually called in the context of std::visit, you will eventually end up with platform-dependent code - at best. Since your visitor class is supposed to appear in the same expression as your variant, you will need at least one interface function to do that. In order to limit the interface, I may do it like this:

    using myvariant=std::variant<TypeA,TypeB>;
    class Visitor
    {
    ...
    private:
        class proxy{
        public:
            proxy(Visitor & that): self{that}{};
            void operator()(TypeA&)&&;//proxy is always rvalue
            void operator()(TypeB&)&&;
         private:
            Visitor &self;
        };
    ...
        void operator()(myvariant& v)//this is my interface function.
        {std::visit(proxy(*this),v);};//only time I use proxy
    };
    ...
    myvariant myval;
    ...
    Visitor myvis;
    ...
    myvis(myval);
    
    

    With this design, I avoid the friendship anti-pattern and expose only one interface function.