2016-09-23 3 views
0

ich folgendes Problem bin vor: ich für boost einige Besucher haben :: Variante, die alle das gleiche für einen bestimmten Typ , hier foo, so dass die Methoderedundanten Code in boost :: variant Besucher zu vermeiden

tun
void operator()(const foo& ast) 
{ 
    //allways the same 
} 

ist immer das gleiche in jedem einzelnen Besucher. Da ich diese redundante Methode nicht in allen Besuchern schreiben möchte, habe ich versucht, das Hinzufügen einer gemeinsamen Basisklasse, die diese Methode implementiert, für alle Besucher zu vermeiden. Problem der Methode ruft die Besucher selbst rekursiv, wie folgt aus:

void operator(const foo& ast) 
{ 
    for(auto&& item : ast.members) 
    { 
     boost::apply_visitor(*this, item); 
    } 
} 

und da alle anderen Methoden, die für die Mitglieder passen in der Basisklasse implementiert Arent, erhalte ich einen Compiler-Fehler, zu diesem Thema. Jetzt ist meine Frage, wie kann ich meinen redundanten Code loswerden? Hier

ist ein Beispiel dafür, wie das Problem aussehen könnte:

struct variant_one; 
struct variant_two; 
struct nil{}; 
typedef boost::variant< 
    boost::spirit::x3::forward_ast<variant_one>, 
    boost::spirit::x3::forward_ast<variant_two>, 
    nil 
> example_variant; 

struct variant_one {}; 
struct variant_two 
{ 
    std::vector<example_variant> members; 
}; 


struct visitor_one : boost::static_visitor<void> 
{ 
    void operator()(const variant_one& ast) 
    { 
     std::cout << "visitor_one detected var_one" << std::endl; 
    } 

    //this is the redundant method 
    void operator()(const variant_two& ast) 
    { 
     std::cout << "visitor detected var_two, output members:" <<std::endl; 
     for(auto&& member : ast.members) 
     { 
      boost::apply_visitor(*this, member); 
     } 
    } 
} 

struct visitor_two : boost::static_visitor<void> 
{ 

    void operator()(const variant_one& ast) 
    { 
     std::cout << "visitor_one detected var_two" << std::endl; 
    } 

    //this is the redundant method 
    void operator()(const variant_two& ast) 
    { 
     std::cout << "visitor detected var_two, output members:" <<std::endl; 
     for(auto&& member : ast.members) 
     { 
      boost::apply_visitor(*this, member); 
     } 
    } 
} 
+2

bitte eine [mcve] –

Antwort

2

So etwas wie das?

template<typename Derived> 
struct VisitorBase { 
    void operator()(const foo& ast) { 
     for(auto&& item : ast.members) { 
      boost::apply_visitor(*static_cast<Derived*>(this), item); 
     } 
    } 
}; 

struct VisitorA : VisitorBase<VisitorA> { 
    void operator()(const ItemType& item) { 
     // do stuff 
    } 
}; 

oder wenn die Besucher verwendeten Typen die gleichen/vorher bekannt und virtuelle Funktionen sind in Ordnung sind:

struct VisitorBase { 
    void operator()(const foo& ast) { 
     for(auto&& item : ast.members) { 
      boost::apply_visitor(*this, item); 
     } 
    } 
    virtual void operator()(const ItemTypeA&) = 0; 
    virtual void opetator()(const ItemTypeB&) = 0; 
}; 

struct VisitorA : VisitorBase { 
    void operator()(const ItemTypeA& item) { 
     // do stuff 
    } 
    void operator()(const ItemTypeB& item) { 
     // do stuff 
    } 
}; 

Im ersten Beispiel Sie sicherstellen möchten vielleicht, dass Sie nicht versehentlich instanziiert die Vorlage mit einem nicht-abgeleiteten Typ, zum Beispiel mit diesem:

static_assert(std::is_base_of<VisitorBase,Derived>::value, "Derived should be derived from VisitorBase"); 

, die noch die Möglichkeit lassen, öffnen ich eine VisitorBase stammende Art von Instanziierung mit einem anderen VisitorBase-abgeleiteten Typ im Template-Parameter, was zu undefiniertem Verhalten führt. Also sei vorsichtig.

+0

vielen Dank, ich denke, die erste sollte in Ordnung sein, ich möchte virtuelle Methoden vermeiden – Exagon

+0

hmm warum nicht einfach http://paste.ubuntu.com/23219932/ – sehe

+1

@ Wie ich es nicht verstanden habe, gibt es mehrere Besucherklassen, die das gepostete Verhalten für den Typ 'foo' teilen, aber unterschiedliche Behavior für andere Typen zu' operator() '. – user4407569

Verwandte Themen