2013-05-29 11 views
5

テンプレートクラス内の関数では、プリミティブ型と他の型を区別しようとしています。 C++ 11ではC++: 'std :: is_fundamental'の代わり?

あなたが行うことができます。

if(std::is_fundamental<T>::value) 
{ 
    // Treat it as a primitive 
} 
else 
{ 
    //Treat it otherwise 
} 

私が間違っていると、これが唯一のC++ 11

にない場合は、Cの以前のバージョンではこれに代わるがあり、私を修正してください++ ?

答えて

8

あなたはこのようにC++ 03でBoost's type traitsを使用することができます。私はこれが同様にC++ 98のために働く必要がありますね

#include <boost/type_traits/is_fundamental.hpp> 

... 

if(boost::is_fundamental<T>::value) 
{ 
    // Treat it as a primitive 
} 
else 
{ 
    //Treat it otherwise 
} 

+0

ありがとうございました。 'インクルード 'の場合+1。 – Subway

2

このコードでは、おかしなことになるでしょう。異なるタイプの特性を区別する必要がある場合、これは実行時ではなくコンパイル時に行う必要があります。実行している操作によっては、ifの2つのブランチのいずれかがコンパイルされないことがあります。したがって、特殊な関数に転送する方が良いでしょう。この実装手法では、使用されたブランチのみをコンパイルする必要があります(つまり正しい)。

編集:

ここではいくつかの追加情報です。この問題に対する解決策は、テンプレートのインスタンス化と関係があります。私はis_fundamentalからis_arrayに切り替えて、どのように操作が失敗するかを示します。

template <class T> 
void fun(T t) { 
    if(boost::is_array<T>::value) 
    { 
     std::cout << "true" << std::endl; 
    } 
    else 
    { 
     std::cout << "false" << std::endl; 
    } 
} 

void f(int i) { 
    fun(i); 
} 

これは、コンパイルして実行し、コンパイラは、if文の1つのブランチのみが使用され、未使用のコードとして他を削除することがわかりますでしょう:

は、最初の例から始めましょう。私は配列操作を使用する場合にはsomeithingを行います私の2番目の例では

template<class T> 
void fun(T& t) { 
    if(boost::is_array<T>::value) 
    { 
     std::cout << t[0]; 
    } 
    else 
    { 
     std::cout << t; 
    } 
} 

void f(int i) { 
    fun(i); 
} 

今ではコンパイルされません。理由は、テンプレート引数としてintがあるとt[0]が形成されているためです。このランタイムステートメントを使用して、コードで必要とされるコンパイル時の型プロパティ(この例では配列を設定するプロパティとt[0]の使用)を区別することはできません。第3の例では

我々は関数のオーバーロードを介して、コンパイル時にdisitinguishます

template<class T> 
void fun_impl(boost::true_type, T& t) { 
    std::cout << t[0]; 
} 

template<class T> 
void fun_impl(boost::false_type, T& t) { 
    std::cout << t; 
} 

template<class T> 
void fun(T& t) { 
    fun_impl(typename boost::is_array<T>::type(),t); 
} 

void f(int i) { 
    fun(i); 
} 

をここis_array<T>::typetrue_type又はfalse_typeのいずれかです。この結果は、コンパイル時にfun_implの正しいオーバーロードを選択するためのセレクタとして使用され、選択されたオーバーロードのみがインスタンス化され、コンパイルされます。

通常、そのような技術は、タイプが特定の特性を有する場合にのみコンパイル可能な最良の実装をコモフィル時間で選択するために使用される。

第二編集:

進路変更のこの意志static ifは言語の一部である場合。

+0

私は他のアプローチで遭遇するかもしれない問題について詳しく教えていただけますか?または説明への参照を追加できますか?私はあなたが書いたことを理解していませんでした。 – Subway

+0

ありがとうございました! +1の精緻化。私はまだ質問があります:私が理解するように、あなたのポイントは、コードをコンパイルし、さらに不要なコードのコンパイルを保存することです。 私のコードがコンパイルされていると、最初の方法で実行時に遭遇するかもしれない実際の問題(予期しない動作のような)がありますか? – Subway

+0

@Subwayいいえコンパイラはあなたのboost :: is_fundamentalを定数として見て、定数として使用し、未使用のコードを削除するので、実行時のオーバーヘッドとUBはありません。アプローチは、それをまったくコンパイルすることです。 const valueメンバはstd :: enable_if(整数テンプレート引数として)を使用するためのものであり、デモンストレーション(値の出力など)のためのものです。他のすべての目的のために、関数のオーバーロードを介してツアーを行うべきだと私は考えます。 –

関連する問題