2013-03-04 2 views

Antwort

19

könnten Sie typeid verwenden:

if (typeid(T) == typeid(int)) 

Oder Sie könnten die std::is_same Typ Merkmal verwenden:

if (std::is_same<T, int>::value) 
+0

Wenn es nur ein 'static_if' ... vielleicht wird dies auf die gleiche Sache lösen – David

+2

Es wurden viele Vorschläge für eine' static_if' gewesen, aber alle hatten Probleme. SG8 schrieb kürzlich [eine Analyse der Vorschläge] (https://docs.google.com/viewer?a=v&pid=forums&srcid=MDIyMDc3NjUwMTczOTM0Mjk3NjABMDI2MzM3MjkxNDM4NDQ5MzE4NDcBLWVsS1Y4dFhtdDhKATUBaXNvY3BwLm9yZwF2Mg & authuser=0). –

+4

@JosephMansfield Der von Ihnen angegebene Link hat keine Vorschau. – kevin

10

Was möchten Sie wahrscheinlich wie ein compile-time if etwas ist. Leider hat C++ 11 keine native Unterstützung für ein solches Sprachkonstrukt.

Wenn Sie jedoch nur, ob zwei Arten identisch sind möchten zu überprüfen, die std::is_same<> Typ Merkmal sollte Ihnen helfen:

#include <type_traits> // <== INCLUDE THIS STANDARD HEADER 

// class template: 
template <class T> 
class mycontainer 
{ 
    T element; 
public: 
    mycontainer (T arg) {element=arg;} 
    T increase() 
    { 
     if (std::is_same<T, int>::value) // <== THIS IS HOW YOU WOULD USE IT 
      return ++element; 

     if (std::is_same<T, char>::value) // <== THIS IS HOW YOU WOULD USE IT 
     { 
      if ((element>='a') && (element<='z')) 
       element+='A'-'a'; 
     } 

     return element; 
    } 
}; 

im Auge behalten jedoch, dass die Bedingungzur Laufzeit ausgewertet wird, obwohl der Wert is_same<T, int>::value zur Kompilierzeit bekannt ist. Das bedeutet, dass sowohl der true als auch der false Zweig der if Anweisung kompilieren müssen!

Zum Beispiel würde die folgende nicht legal sein:

if (std::is_same<T, int>::value) 
{ 
    cout << element; 
} 
else if (std::is_same<T, my_class>::value) 
{ 
    element->print(); // Would not compile when T is int! 
} 

Auch als Xeo richtig in den Kommentaren darauf hingewiesen, wird der Compiler wahrscheinlich Warnungen ausgeben, weil Ihr Zustand immer zu true evaluieren oder zu false, einer der beiden Zweige enthält also nicht erreichbaren Code.

+0

C++ hat Kompilierzeit 'if': es heißt Funktion Überladungsauflösung. –

+0

Und das bedeutet auch, dass Sie Warnungen für die Zweige erhalten, die nicht verwendet werden. Die bessere Form wäre das Tag-Dispatching, und ich dachte mir das für meine Antwort, aber das einfache Überladen macht auch den Job. – Xeo

+0

@JamesKanze: Das ist nichts wie ein richtiges statisches if-Konstrukt. –

6

Wie wäre es mit einer einfachen Überladung?

// in the private section 
static int& do_increase(int& i){ return ++i; } 
static char& do_increase(char& c){ 
    if(c >= 'a' && c <= 'z') 
    c += 'A' - 'a'; 
    return c; 
} 
template<class U> 
static U& do_increase(U& arg){ 
    // some default implementation? 
    return arg; 
} 

(Beachten Sie, dass der Standard nicht alphabetischen Reihenfolge für die numerischen Werte eines char garantiert.)

Dann einfach, dass als return do_increase(element); in increase nennen.

3

Die übliche Lösung ist hier die Weiterleitung auf eine überladene Funktion mit einem zusätzlichen Argument. Etwas wie:

template <typename T> 
class MyContainer 
{ 
    T increase(int const*) { /* special treatment for int */ } 
    T increase(...)  { /* default treatment   */ } 
public: 
    T increase() 
    { 
     return increase((T const*)0); 
    } 
}; 

Mit einer wenig Phantasie kann man mit allen möglichen Scheidungen kommen. Wenn Sie die Zielfunktionen mit den zusätzlichen Argumentenschablonen ausführen, können Sie sogar SFINAE: design das Dummy-Argument nutzen, sodass die Schablonentyp-Substitution fehlschlägt, und wird die Funktion in der Überladungsgruppe nicht berücksichtigt. Und Da alle Funktionen inline sind, ist es wahrscheinlich, dass keine zusätzlichen Overhead sein wird, vorausgesetzt, dass Sie optimieren.

+0

Der interne 'Anstieg' Aufruf benötigt nicht das Template-Argument (in der Tat wäre es ein Fehler). – Xeo

+0

@Xeo Korrigieren. Ich hatte ursprünglich etwas generischeres getan, was es erforderte, dass die beiden Zielfunktionen Vorlagen waren (für SFINAE). Ich werde es hier reparieren. –

0

Dies ist in Anlehnung an die Antwort von Andy Prowls, aber alles wird zur Kompilierzeit mit einer minimalen Hilfsklasse mit Spezialisierung gemacht.

In diesem Fall haben Sie einen Helfer, der tatsächlich die Spezialisierung ausführt, aber Sie könnten auch die Helferklasse einfach einen bool nehmen und dann etwas wie std::is_same<T, int>::value verwenden, um diesen Wert als Vorlageparameter zu übergeben.

template <typename T> 
struct myContainerHelper; 
{ 
    // General Case 
    static inline T increase(T element) 
    { 
     return ++element; 
    } 
}; 

template <> 
struct myContainerHelper<char> 
{ 
    // Specific case 
    static inline char increase(char element) 
    { 
     if ((element>='a')&&(element<='z')) element+='A'-'a'; 
     return element; 
    } 
}; 

template <class T> 
class mycontainer 
{ 
    T element; 
public: 
    mycontainer (T arg) {element=arg;} 
    T increase() 
    { 
     return myContainerHelper<T>::increase(element); 
    } 
}; 

Auf diese Weise können Sie die einzige Funktion statt der gesamten Klasse nur spezialisieren. Ich verwende eine Template-Klasse mit Statik, weil ich an VS2012-Einschränkungen mit teilweiser Spezialisierung für Funktionsvorlagen gewöhnt bin.

5

Sie explizite Template-Spezialisierung verwenden

#include <iostream> 
using namespace std; 

// class template: 
template <class T> 
class mycontainer { 
    T element; 
    public: 
    mycontainer (T arg) {element=arg;} 
    T increase(); 
}; 


template<> 
int mycontainer<int>::increase(){ 
    return ++element; 
} 

template<> 
char mycontainer<char>::increase(){ 
    if ((element>='a')&&(element<='z')) 
     element+='A'-'a'; 
    return element; 
} 

int main(){ 
     mycontainer<int> A(10); 
     mycontainer<char> B('x'); 

     cout << A.increase() <<endl; 
     cout << B.increase() <<endl; 
     return 0; 
} 
+0

Ich mag diese Lösung – Dmitri

Verwandte Themen