2

如何使boost::apply_visitor(两种变体中的任何一种)成为班级访问者的朋友功能?

我尝试了以下方法:friend result_type boost::apply_visitor<>(decltype(*this) &, instruction_type const &);,但这不起作用。*this派生自boost::static_visitor(或具有using result_type = ...;typedef)并且指令类型是boost::variant某些特定类型的。*this在部分中有所有必需operator ()的 -s private

这种声明的正确形式是什么?

4

1 回答 1

3

如果您坚持,您可以将您的实际访问者包装在一个暴露所需接口的访问者中,并将其声明您的访问者-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 上看到这一切

于 2013-09-07T15:36:28.823 回答