Reputation: 16731
How to make the boost::apply_visitor
(either of two variants) a friend-function of class-visitor?
I have tried the following: friend result_type boost::apply_visitor<>(decltype(*this) &, instruction_type const &);
, but this does not work. *this
derived from boost::static_visitor
(or have using result_type = ...;
typedef) and instruction type is the boost::variant
of some specific types. *this
have all required operator ()
-s in private
section.
What is the right form of such declaration?
Upvotes: 2
Views: 559
Reputation: 393259
If you insist, you could wrap your actual visitor in a visitor that exposes the required interface, and declare that as a friend of your visitor-impl (that now combines the impl and visitor concepts).
(The "good" (cough) thing here is that there is not need for the impl
to be polymorphic or dynamically allocated.)
Here's a stratight-forward proof of concept:
#include <boost/variant.hpp>
namespace detail
{
template <typename R, typename Wrapped>
struct WrapVisitor : boost::static_visitor<R>
{
template <typename... T> R operator()(T&&... args) const { return _wrapped(std::forward<T>(args)...); }
WrapVisitor(Wrapped&& wrapped) : _wrapped(std::move(wrapped)) {}
private:
Wrapped _wrapped;
};
}
template <typename R, typename Wrapped>
detail::WrapVisitor<R, Wrapped> wrap(Wrapped&& wrapped) {
return { std::forward<Wrapped>(wrapped) };
}
And here's how you'd use it with a demo visitor that hides all implementation details:
class PrivateVisistorImp : protected boost::static_visitor<double>
{
double operator()(int i) const { return -i; }
double operator()(double d) const { return d*10; }
friend detail::WrapVisitor<double, PrivateVisistorImp>;
};
Of course, it has the cost of needing to instantiate the wrapped visitor at the call site:
int main()
{
using Var = boost::variant<int, double>;
Var a = 3.14, b = 42;
auto w = wrap<double>(PrivateVisistorImp());
std::cout << boost::apply_visitor(w, a) << "\n";
std::cout << boost::apply_visitor(w, b) << "\n";
}
See it all Live on Coliru
Upvotes: 3