5

テンプレート クラス内の関数で、プリミティブ型とそれ以外を区別しようとしています。

C++ 11 では、次のことができます。

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

私が間違っている場合は修正してください。これは c++ 11 だけではありません。

以前のバージョンの C++ でこれに代わるものはありますか?

4

2 に答える 2

8

次のように、C++03 でBoost の型特性を使用できます。

#include  <boost/type_traits/is_fundamental.hpp>

...

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

これは C++98 でも機能するはずです。

于 2013-05-29T07:04:24.683 に答える
2

このコードを使用すると、問題が発生する可能性があります。異なる型特性を区別する必要がある場合は、実行時ではなくコンパイル時に行う必要があります。実行している操作によっては、2 つのブランチのいずれかがifコンパイルされない場合があります。したがって、特殊な関数に転送することをお勧めします。

void operation_impl(boost::true_type /*other params*/) {
  // Treat it is primitive 
}

void operation_impl(boost::false_type /*other params*/) {
  // Treat it otherwise
}

template<class T>
void operation(/* params*/) {
  operation_impl(boost::is_fundamental<T>::type() /*other params*/);
}

この実装手法では、使用されたブランチのみをコンパイルする必要があります (つまり、正しい)。

編集:

ここにいくつかの追加情報があります。この問題の解決策は、テンプレートのインスタンス化に関係しています。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 つの分岐のみが使用されることを確認し、他の分岐を未使用のコードとして削除します。

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 番目の例では、関数のオーバーロードによってコンパイル時間を区別します。

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>::typeは または のいずれtrue_typefalse_typeです。この結果はfun_impl、コンパイル時に適切なオーバーロードを選択するためのセレクターとして使用され、選択されたオーバーロードのみがインスタンス化されてコンパイルされます。

通常、このような手法は、型が特定のプロパティを持っている場合にのみコンパイル可能な最適な実装をコンパイル時に選択するために使用されます。

2回目の編集:

static if言語の一部である場合、これはもちろん変更されます。

于 2013-05-29T10:46:11.143 に答える