2017-09-08 6 views
2

Je dois créer l'objet boost::variant et utiliser static_visitor. Malheureusement j'ai besoin de paramètres supplémentaires ...Argument supplémentaire dans operator() dans boost :: static_visitor

Quelle est la meilleure solution? Pour avoir cet objet comme champ de la classe et quand je veux utiliser visiteur je dois créer une instance:

class Visitor : public boost::static_visitor<> 
{ 
public: 
    Visitor(int extra): extra{extra} {} 
    void operator()(const T1&) { /* ... */} 
    void operator()(const T2&) { /* ... */} 

private: 
    int extra; 
}; 

et créer des visiteurs objet chaque fois que je veux l'utiliser:

Visitor visitor(x); 
boost::apply_visitor(visitor, t); 

ou utiliser boost :: bind et créer Visitor une fois et utiliser boost::bind?

class Visitor : public boost::static_visitor<> 
{ 
public: 
    void operator()(const T1&, int extra) { /* ... */ } 
    void operator()(const T2&, int extra) { /* ... */ } 
}; 

Utilisation:

auto visitor = std::bind(SctpManager::Visitor(), std::placeholders::_1, extra); 
boost::apply_visitor(visitor, t); 

Ce qui est mieux (plus rapide, plus élégante) solution?

Ou y at-il de meilleures solutions?

Répondre

1

Il n'y a pas essentiellement manière plus élégante. Vous pouvez utiliser lambdas (si votre version compilateur/boost est assez moderne).

L'option "low-tech" est d'utiliser une struct qui maintient l'état (3ème exemple):

Live On Coliru

#include <boost/variant.hpp> 
#include <iostream> 

struct T1{}; 
struct T2{}; 

struct Visitor : boost::static_visitor<> 
{ 
    void operator()(T1 const&, int extra) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; } 
    void operator()(T2 const&, int extra) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; } 
}; 

int main() { 
    boost::variant<T1, T2> tests[] = { T1{}, T2{} }; 

    { 
     Visitor vis; 
     for (auto v: tests) 
      apply_visitor([=](auto const& v) { vis(v, 42); }, v); 
    } 

    { 
     auto vis = [vis=Visitor{}](auto const& v) { vis(v, 1); }; 
     for (auto v: tests) 
      apply_visitor(vis, v); 
    } 


    { 
     struct { 
      using result_type = void; 
      int extra; 
      void operator()(T1 const&) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; } 
      void operator()(T2 const&) const { std::cout << __PRETTY_FUNCTION__ << " extra:" << extra << "\n"; } 
     } vis { 99 }; 

     for (auto v: tests) 
      apply_visitor(vis, v); 
    } 
} 

Prints

void Visitor::operator()(const T1&, int) const extra:42 
void Visitor::operator()(const T2&, int) const extra:42 
void Visitor::operator()(const T1&, int) const extra:1 
void Visitor::operator()(const T2&, int) const extra:1 
void main()::<unnamed struct>::operator()(const T1&) const extra:99 
void main()::<unnamed struct>::operator()(const T2&) const extra:99