2013-09-07 3 views
2

Как сделать boost::apply_visitor (любой из двух вариантов) функцией friend-class-visitor?Как сделать 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 раздел.

Какая форма такой декларации?

+1

Почему бы это _need_ быть? Это выглядит как ненужное осложнение для меня. 'apply_visitor' ожидает' static_visitor <> 'производный класс с открытым интерфейсом. Просто поставьте его:/ – sehe

+0

@sehe Мой посетитель - это шаблон шаблона. Поэтому я должен поместить всю логику в заголовок, но я хочу иметь «некоторую остаточную сумму» 'private'ness (чтобы обеспечить инкапсуляцию как можно больше). – Orient

+0

Затем используйте pimpl для «частного» материала. Вы не можете скрыть общий интерфейс. Не нужно. – sehe

ответ

3

Если вы настаиваете, вы можете обернуть своего посетителя посетителем, который предоставит требуемый интерфейс, и объявите , что в качестве друга вашего посетителя-имплантата (который теперь объединяет концепции impl и посетителя).

(«Хороший» (кашель) здесь является то, что не нужно для impl полиморфными или динамически распределяемой.)

Вот stratight вперед доказательство концепции:

#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"; 
} 

видеть все это Live on Coliru

+1

Я полностью не понимаю, что вы хотели там сказать. Для развлекательной ценности, здесь [версия, которая даже «поднимает» «noexcept'-ness обернутого посетителя] (http://coliru.stacked-crooked.com/a/23f7129872bd450e) :) – sehe

Смежные вопросы