2017-05-05 1 views
4

Ich versuche das Programm zu erstellen, das nur dann Code ausführt, wenn das Template instanziiert wird (es wird für die Low-Level-Treiberinitialisierung verwendet). Jetzt habe ich folgende Lösung.Instantiierung der statischen Instance des Force-Templates

class Initializer 
{ 
public: 
    Initializer(){ 
     // This code is executed once 
    } 

    void silly() const{ 

    } 
}; 

template <class T> 
class Proxy{ 
protected: 
    static const Initializer init; 
}; 

template<class T> 
const Initializer Proxy<T>::init; 

template<class T> 
class MyTemplate : public Proxy<void>{ 
public: 
    static void myMethod1(){ 
     init.silly(); 

     // ... Something useful 
    } 

    static void myMethod2(){ 
     init.silly(); 

     // ... Something useful 
    } 
}; 

Der Initializer Standardkonstruktors ist Fall, dass ich myMethod1() oder myMethod2() irgendwo rufen nur in ausgeführt.

Aber gibt es eine Möglichkeit, diese init.silly(); Linien loszuwerden?

+0

"Instanziierung erzwingen" und "Instanziierung überprüfen" sind zwei ziemlich unterschiedliche Dinge. –

+0

Möchten Sie 'Initializer' für jede Instantiierung von' Proxy' erstellen? Z.B. Wenn Sie 'Proxy ' und 'Proxy ' erstellen, wird 'Initializer' zweimal erstellt? – Pavel

+0

Nein, ich möchte nur eine Instanz von 'Initialisierer' erstellen. Ich werde immer von "Proxy " erben. – valentin

Antwort

2

Ihr Problem ist, dass Mitglieder einer Vorlage nicht instanziiert werden, wenn sie nicht referenziert werden.

Rather init.silly() als Aufruf, können Sie verweisen nur das Mitglied:

static void myMethod1(){ 
     (void)init; 

     // ... Something useful 
    } 

Oder, wenn Sie init wollen unbedingt immer definiert werden, können Sie es explizit instanziiert:

template<> 
const Initializer Proxy<void>::init{}; 
+0

Es ist besser, erfordert aber immer noch eine zusätzliche Codezeile. Wenn ich die explizite Instantiierung von 'init' verwende, wird ihr Konstruktor ausgeführt, auch wenn' MyTemplate' nicht instanziiert wird. Das ist nicht der Fall. – valentin

1

Vorlage und Low-Level-Treiberinitialisierung? .. Ich würde versuchen, es so C wie möglich zu machen :), um genaues Verhalten sicherzustellen.

Sie können wie diese vielleicht etwas tun:

class Initializer 
{ 
public: 
    Initializer() { 
     // This code is executed once 
    } 
}; 

template <class T> 
class Proxy { 
protected: 
    Proxy() 
    { 
     static Initializer init; 
    } 
}; 

template<class T> 
class MyTemplate : public Proxy<void> { 
public: 
    void myMethod1() { 
     // ... Something useful 
    } 

    void myMethod2() { 
     // ... Something useful 
    } 
}; 

Alle Code verwendet nur statische Funktionen und zeigt nicht wirklich, warum Sie Klassen und Vorlagen verwenden würden. Mit meiner Änderung machte ich myMethod1 und myMethod2 nicht statischen und Proxy() Konstruktor würde Initializer einmal erstellen.

Beachten Sie, dass wegen all dieser Vorlage Chaos Ihre Initializer möglicherweise so oft ausgeführt werden, wie Sie Proxy-Vorlage instanziieren. Hast du es wirklich ernst gemeint? Wenn nicht, konvertieren Sie in den lesbaren Code, der diese unerwarteten Ergebnisse nicht aufweist. Dies wird auch besser wartbar und lesbar für andere:

class Initializer 
{ 
    Initializer() { 
     // This code is executed once 
    } 
public: 
    void init() 
    { 
     static Initializer init; 
    } 
}; 


template<class T> 
class MyTemplate { 
public: 
    static void myMethod1() { 
     Initializer::init(); 
     // ... Something useful 
    } 

    static void myMethod2() { 
     Initializer::init(); 
     // ... Something useful 
    } 
}; 

Dies macht es absolut klar, dass Initializer wird nur einmal erstellt werden kurz vor myMethod1 oder myMethod2 genannt wird. Wenn nichts Ihre Initializer::init anruft, sollte dieser Code von Initializer zur Verbindungszeit entfernt werden.

+0

Oh ja! Das ist viel sauberer. Es erspart Ihnen auch, sich um detaillierte Fragen zu kümmern, wann ein Template-Member instanziiert wird - das ist nur die Art von dunkler Ecke des Standards, über die sich a) Entwickler irritieren; b) * Compiler * Entwickler werden gelegentlich verwirrt. –

Verwandte Themen