如果您坚持,您可以将您的实际访问者包装在一个暴露所需接口的访问者中,并将其声明为您的访问者-impl(现在结合了 impl 和访问者概念)的朋友。
(这里的“好”(咳嗽)是不需要impl
多态或动态分配的。)
这是一个直截了当的概念证明:
#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) };
}
以下是您如何将它与隐藏所有实现细节的演示访问者一起使用:
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>;
};
当然,它需要在调用站点实例化包装的访问者的成本:
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";
}
在 Coliru 上看到这一切