2012-04-04 8 views
1

Gibt es eine Möglichkeit, zur Kompilierungszeit einen von zwei Laufzeitcodepfaden zu bestimmen? Ich bin mir bewusst, dass das Überladen von Funktionen verwendet werden kann, um dieses Kunststück zu erreichen, aber dann steigt die Code-Größe, weil beide meiner Funktionen kompiliert und in das Programm eingebunden sind. Gibt es eine Möglichkeit, diesen Overhead zu vermeiden?C++ Compile-Time Conditional-Laufzeitanweisungen

Wesentlichen, was ich tun möchte, ist:

#include <boost/mpl/if.hpp> 
#include <boost/type_traits/is_abstract.hpp> 

template <class T> 
    class X 
{ 
    public: 
     void copy_t(T &old_t) 
     { 
      // 
      // if T is abstract, (meaning that t is a pointer) 
      // 
      t = old_t.clone(); 

      // 
      // else 
      // 
      t = old_t; 
     } 

    private: 
     typename boost::mpl::if_<boost::is_abstract<T>, T *, T>::type t; 
}; 

Der einzige Weg, ich weiß, geht überladenen Member-Funktionen:

template <class T> 
    class X 
{ 
    public: 
     void copy_t(T &old_t) 
     { 
      t = make_copy(old_t, t); 
     } 

    private: 
     T *make_copy(T &old_t, T *t) 
     { 
      return old_t.clone(); 
     } 

     T &make_copy(T &old_t, T &t) 
     { 
      return old_t; 
     } 

     typename boost::mpl::if_<boost::is_abstract<T>, T *, T>::type t; 
}; 

Aber jetzt, zwei make_copy Mitgliederfunktionen zusammengestellt und in die verlinkte Programm, obwohl X immer nur mit einem abstrakten Klassenvorlagenparameter instanziiert werden kann, in welchem ​​Fall nur einer von ihnen benötigt wird.

+0

Wird der Optimierer die nicht aufgerufenen Funktionen nicht entfernen? – Nick

+2

Lassen Sie mich das klarstellen: Sie sind besorgt über die zusätzlichen Kosten einer Einzeiler-Funktion in Ihrer endgültigen ausführbaren Datei? –

+0

Beachten Sie auch, dass Sie einige Annahmen im Code treffen, z. B. sind alle Objekte eines nicht abstrakten Typs ein vollständiges Objekt. I.e. Wenn Sie einen Typ haben, der einen anderen nicht abstrakten Typ erweitert, und die Funktion für den Zwischentyp aufgerufen wird, werden Sie geschnitten. Ihre Schnittstelle scheint das * zu bieten, was in jedem Fall das Beste ist * Versprechen (entweder kopieren/klonen), liefert dann aber nicht immer das Versprechen. –

Antwort

3

Aus Ihren Beispielen sieht es so aus, als ob die Funktionen Mitglieder einer Klasse Vorlage sind. Wenn ja, werden sie nur instanziiert, wenn sie tatsächlich verwendet werden; Wenn die Überladungsauflösung immer eine davon auswählt, wird die andere niemals instanziiert.

Dies ist eine kritische Regel für viele Meta-Programmiertechniken. Es ist nicht selten in solchen Fällen, dass die Funktion, die nicht instanziiert wird verursachen Fehler bei der Kompilierung, wenn es instanziiert wurde.