2013-03-04 25 views
21
// template specialization 
#include <iostream> 
using namespace std; 

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

    //if(T.type==int)//how to do this or something similar? 
    //do this if an int 
    return ++element; 

    //if(T.type==char) 
    //if ((element>='a')&&(element<='z')) 
     //element+='A'-'a'; 
     //return element; 

    } 
}; 

私はテンプレートの専門化を書いて、char型のために別個の全体クラスのdefを行う方法を知っています。C++のテンプレートでif else型の型を処理する方法は?

しかし、1ブロックのコードですべてを処理したい場合はどうすればよいですか?

Tがintかcharかどうかを確認するにはどうすればよいですか?

答えて

19

あなたはtypeid使用することができます

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

をそれとも、std::is_same型特性使用することができますあなたが望む

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

のみがあった場合は、 'static_if' ...多分これは同じことに解決されます – David

+2

あり' static_if'のための多くの提案されているが、すべてを持っていました問題。 SG8は最近、[提案の分析](https://docs.google.com/viewer?a=v&pid=forums&srcid=MDIyMDc3NjUwMTczOTM0Mjk3NjABMDI2MzM3MjkxNDM4NDQ5MzE4NDcBLWVsS1Y4dFhtdDhKATUBaXNvY3BwLm9yZwF2Mg&authuser=0)を書きました。 –

+4

@JosephMansfieldあなたがあなたへのリンクにプレビューはありません。 – kevin

10

はおそらくcompile-time ifのようなものです。残念なことに、C++ 11にはこのような言語構造のネイティブサポートはありません。あなただけの2種類が同一であるかどうかを確認したい場合は

しかし、std::is_same<>型特性はあなたを助ける必要があります。

#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; 
    } 
}; 

しかし、条件が実行時でを評価されていることに注意してくださいコンパイル時にはis_same<T, int>::valueの値がわかっていますが、これは、truefalseifステートメントのブランチは、をコンパイルする必要があることを意味します。

たとえば、次は合法ではないでしょう。また

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! 
} 

Xeoが正しくコメントで指摘したように、あなたの条件は常にtrueまたはfalseに評価されるため、コンパイラはそう警告を発行します、 2つのブランチの1つに到達できないコードが含まれます。

+0

C++はコンパイル時に 'if'を持っています。関数オーバーロードの解決と呼ばれます。 –

+0

これはまた、使用されていないブランチに対して警告を受け取ることを意味します。これのより良い形はタグディスパッチングであり、私はそれを私の答えに考えましたが、単純なオーバーロードもその仕事をしています。 – Xeo

+0

@ JamesKanze:それは本当の '静的な' if構造体のようなものではありません。 –

6

単純なオーバーロードはどうですか?

// 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; 
} 

(標準はcharの数値のアルファベット順を保証するものではないことに注意してください。)

そして、単にreturn do_increase(element);としてincreaseのそれを呼び出します。

3

ここでの通常の解決策は、オーバーロードされた関数 に追加の引数を付けて転送することです。ような何か:少し想像して

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); 
    } 
}; 

、あなたは 区別のすべての種類を思い付くことができます。 引数テンプレートを追加してターゲット関数を作成すると、SFINAEを利用することもできます。 ダミー引数を使用すると、テンプレート型の置換に失敗し、 関数はオーバーロードセットでは考慮されません。そして、 の機能はすべてインラインであるため、 には特別なオーバーヘッドはありません。

+0

内部の 'increase'呼び出しはテンプレート引数を必要としません(実際にはエラーになります)。 – Xeo

+0

@Xeo正しい。私はorginallyより一般的な、2つのターゲット関数(SFINAEの再生に来る)のテンプレートを必要とする何かをやった。私はここでそれを修正します。 –

0

これはAndy Prowlsの答えに沿っていますが、すべてコンパイル時に特殊化された最小ヘルパークラスを使用して行われます。

この場合、実際には特殊化を行うヘルパーがありますが、ヘルパークラスにはブール値を受け取り、std::is_same<T, int>::valueなどの値をテンプレートパラメータとして渡すこともできます。

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); 
    } 
}; 

これにより、クラス全体ではなく、1つの関数のみを特殊化することができます。関数テンプレートの部分的な特殊化でVS2012の制限に慣れているので、私は静的なテンプレートクラスを使用しています。あなたが明示的なテンプレートの特殊化を使用することができ

5

#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

私はこの解決策が好きです – Dmitri

関連する問題