2015-05-09 8 views
6

Ich habe eine Hierarchie von Operationen und (geteilten) Informationsklassen, in denen intuitiv scheint es keine Notwendigkeit für Laufzeitpolymorphismus, und doch kann ich keine Lösung ohne es finden.CRTP mit einer zyklischen Abhängigkeit

Für diese Frage angenommen, es gibt eine 2-Level-Hierarchie. Es gibt eine Basisoperation und eine abgeleitete Operation. Objekte auf derselben Hierarchiestufe müssen möglicherweise Informationen zwischen ihnen austauschen (dh, dass Basisoperationsobjekte Basisinformationen gemeinsam nutzen müssen und abgeleitete Operationsobjekte abgeleitete Informationen gemeinsam nutzen müssen, Basisoperationsobjekte jedoch niemals abgeleitete Informationen oder Laster gemeinsam nutzen müssen versa).

So beginnt es wie folgt aus:

// Shared between base operation objects 
class base_info 
{ 

}; 

// Shared between derived operation objects 
class derived_info : 
    public base_info 
{ 

}; 

Da gibt es keine Laufzeit-Frage, über die Operation Anteil Objekte, die Informationsobjekte, gibt es auch die folgende ist:

template<class Info> 
class base_op 
{ 
    std::shared_ptr<Info> m_info; 
}; 

class derived_op : 
    public base_op<derived_info> 
{ 

}; 

Der Rest der Code instanziiert immer base_op mit base_information, und so ist hier kein Laufzeitpolymorphismus erforderlich.

Jetzt können die gemeinsam genutzten Informationsobjekte an einigen Punkten entscheiden, dass sie neue Operationen generieren müssen. Wie oben gesehen, benötigen Operationsobjekte gemeinsam benutzte Zeiger auf geteilte Informationsobjekte. So ist die Informationshierarchie wechselt:

// Shared between base operation objects 
class base_info : 
    private std::enable_shared_from_this<base_info> 
{ 
    void do_something_spawning_new_ops(); 
}; 

... 

Das Problem ist nun, wie do_something_spawning_new_ops zu implementieren. Mit Laufzeit polymporphism, dann ist es nicht so schwierig:

class base_info : 
    private std::enable_shared_from_this<base_info> 
{ 
    void do_something_spawning_new_ops() 
    { 
     // Need a new op. 
     get_op_shared_ptr(); 
    } 

    virtual std::shared_ptr<base_op> get_op_shared_ptr() 
    { 
     // use shared_from_this, create a base_op object using it. 
    } 
}; 

class derived_info : 
    public base_info 
{ 
    virtual std::shared_ptr<base_op> get_op_shared_ptr() 
    { 
     // use shared_from_this + std::*_pointer_cast, 
     // create a derived_op object 
    }  
}; 

aber der Punkt ist Runtime Polymorphismus zu vermeiden, da durch Design, alles kann bei der Instanziierung bekannt sein. So zu Beginn des Posts zurück, wäre es so etwas wie dies schön gewesen sein zu haben:

template<class Op> 
class base_info 
{ 

}; 

class derived_info : 
    public base_info<derived_op> 
{ 

}; 

mit CRTP Art von Dingen (wenn auch ohne die Ableitung), wo die op sagt, dass es eine Info hält die Schaffung Objekte dieses Typs. Dies verursacht nun jedoch ein zyklisches Problem für die Instanziierung von base_op. Es muss irgendwie durch irgendeinen Informationstyp instanziiert werden, der selbst durch seinen eigenen Typ instanziiert wird, usw. usw. Ich weiß nicht, wie man diesen Typzyklus abbremst.

bearbeiten

Nach Panta rhei Anregung here ist der Code, den ich für Ziel bin.

+2

CRTP beinhaltet Downcasting von Base zu abgeleitet. Ich sehe das nirgendwo hier. Geben Sie ein vollständiges, aber minimales Beispiel für Code an, der das Problem veranschaulicht. –

+0

Zyklische Abhängigkeiten können durch Verzögerung der Template-Instanziierung gelöst werden. Dies kann durch Hinzufügen einer weiteren Ebene erfolgen. – rpress

+0

Sie haben eine Menge unbekannter/vager Sachen in Ihrer Frage hinterlassen. Bitte geben Sie einen [MCVE] (http://stackoverflow.com/help/mcve) an oder zumindest einen Link zu einem, z. mit einer Online-IDE wie [Ideone] (http://ideone.com/). –

Antwort

3

Ich bin immer noch nicht ganz sicher, was Sie erreichen wollen, aber alles, was Sie tun müssen, um Ihren Code kompilieren zu lassen, ist ein type-Argument in der base_info-Klassenvorlage hinzuzufügen, wenn Sie es in main instanziieren.

int main() 
{ 
    derived_op d; 
    base_op<base_info<derived_info> > b; 
}