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
};
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 friend
ship anti-pattern and expose only one interface function.