2016-05-12 6 views
2

I Container mit einem Template-Konstruktor eine Template-Klasse haben wie folgt definiert:Bedingtes default-konstruierbar Klassen eines Parameters Pack konstruieren

template<class... Objects> 
class Container 
{ 
public: 
    template<class... Objs> 
    Container(Objs*... objs) 
    { 
     // initialize all pointers of m_objs to nullptr 
     objs_init<Objects...>(); 

     // initialize the pointers of m_objs corresponding to parameters pack objs... 
     objs_init<Objs...>(objs...); 
    } 

private: 
    template<class Obj, class O1, class ...On> 
    void objs_init() 
    { 
     objs_init<Obj>(); 
     objs_init<O1, On...>(); 
    } 
    template<class Obj, class O1, class ...On> 
    void objs_init(Obj* obj, O1* o1, On*... on) 
    { 
     objs_init<Obj>(obj); 
     objs_init<O1, On...>(o1, on...); 
    } 
    template<class Obj> 
    void objs_init(Obj* obj = nullptr) 
    { 
     std::get<Obj*>(m_objs) = obj; 
    } 

    std::tuple<Objects*...>  m_objs; 
}; 

und einige Klassen A, B, C, ... wie folgt definiert:

class A { public: A(bool) {} }; 
class B { /*trivial default ctor*/ }; 
class C { public: C(int) {} }; 

Wenn ich ein Container<A,B,C> Objekt auf diese Weise:

Container<A,B,C> cnt(new A(true), new C(1)); 

alle Klassen unter der Annahme, in Template-Parametern angegebenen verschieden sind, der Container<> Template-Konstruktor funktioniert wie erwartet, das heißt:

  • alle Zeiger des m_objs Tupel ist erster Satz nullptr, dann
  • die erste (A*) und 3. (C*) Zeiger von m_objs werden durch new A(true)new C(1) und jeweils mit den zurückgegebenen Werte eingestellt.

Nun würde Ich mag den Container<> Konstruktor alle nicht initialisierten Zeiger von m_objs default-konstruieren. Aber ich weiß nicht, wie ich das erreichen soll.

Ich habe versucht, die folgenden Vorlagen-Element-Funktionen Container<> Zugabe:

template<class Obj, class O1, class ...On> 
    void objs_ctor() 
    { 
     objs_ctor<Obj>(); 
     objs_ctor<O1, On...>(); 
    } 
    template<class Obj> 
    void objs_ctor() 
    { 
     Obj*& obj = std::get<Obj*>(m_objs); 
     if (obj == nullptr) 
      obj = new Obj; 
    } 

und einen Aufruf an objs_ctor<> in Container<> Konstruktor:

 // default-construct unitialized pointers of `m_objs` 
     objs_ctor<Objects...>();    

dies jedoch offensichtlich nicht funktioniert, weil die Art, wie ich umgesetzt objs_ctor<> erfordert, dass ein Default-Konstruktor für alle Klassen des Parameters Pack existiert (was ich will nicht); so erhalte ich den folgenden Compiler-Fehler:

error C2512: 'A' : no appropriate default constructor available 

Damit dies funktioniert, muß ich auch überprüfen, ob das Objekt Ich versuche, automatisch zu erstellen default-konstruierbar ist. Ich denke, das könnte mit std::is_default_constructible<> erreicht werden, aber ich weiß nicht, wie man es richtig benutzt.

Danke für Hilfe.

Antwort

2

Hypothese.

einen Aufruf an objs_ctors<Objects...>(); in Konstruktor hinzufügen

template<class... Objs> 
    Container(Objs*... objs) 
     { 
     objs_init<Objects...>(); 
     objs_init<Objs...>(objs...); 
     objs_ctors<Objects...>(); 
     } 

und

template <typename Obj> 
    typename std::enable_if<true == std::is_default_constructible<Obj>::value, void>::type objs_ctor() 
     { 
     Obj * & obj = std::get<Obj*>(m_objs); 

     if (obj == nullptr) 
      obj = new Obj; 
     } 

    template <typename Obj> 
    typename std::enable_if<false == std::is_default_constructible<Obj>::value, void>::type objs_ctor() 
     { } 

    template <typename Obj, typename O1, typename ... On> 
    void objs_ctors() 
     { 
     objs_ctor<Obj>(); 
     objs_ctors<O1, On...>(); 
     } 

    template <typename Obj> 
    void objs_ctors() 
     { 
     objs_ctor<Obj>(); 
     } 

Achtung objs_ctor<>() und objs_ctors<>() auf diese Weise definieren, bitte: Ich nehme an Ihrem Beispiel

Obj*& obj = std::get<Obj*>(m_objs); 
    if (obj != nullptr) 
     obj = new Obj; 

war falsch .

Ich nehme Ihre Absicht ändern war (zuzuteilen) obj wenn obj ein nullptr ist, so

Obj*& obj = std::get<Obj*>(m_objs); 
    if (obj == nullptr) 
     obj = new Obj; 

P. S .: sorry für mein schlechtes Englisch.

+0

Sie vermutlich gut. Frage bearbeitet – shrike

Verwandte Themen