1

「文字、符号付き整数、符号なし整数、浮動小数点、ポインター」など、型の品質に基づいて特殊化したい関数がいくつかあります。type_traitsを使用することはこれを行う方法ようであり、次のようなコードがあります。

#include <tr1/type_traits>
#include <iostream>

template<bool, typename _Tp = void>
struct enable_if 
{ };

template<typename _Tp>
struct enable_if<true, _Tp>
{
    typedef _Tp type;
};


template< typename T >
inline void
foo_impl( typename enable_if< std::tr1::is_integral< T >::value, T >::type const& )
{
    std::cout << "This is the function-overloaded integral implementation.\n";
}

template< typename T >
inline void
foo_impl( typename enable_if< std::tr1::is_floating_point< T >::value, T >::type const& )
{
    std::cout << "This is the function-overloaded floating-point implementation.\n";
}

template< typename T >
inline void
function_overloads_foo( T const& arg )
{
    foo_impl< T >( arg ); // vital to specify the template-type
}

void function_overloads_example()
{
    function_overloads_foo( int() );
    function_overloads_foo( float() );
}

私の実際のコードを除いて、私は、、なども持ってbarbazますfoo

ただし、品質ごとにこれらすべての関数をメソッドとして1つのテンプレートクラスにグループ化したいと思いstaticます。これはどのように行うのが最善ですか?これが私の素朴で壊れたタグ、SFINAE、および部分的特殊化の使用の試みです。

struct IntegralTypeTag;
struct FloatingPointTypeTag;

template< typename T, typename U = void >
class Foo
{
};

template< typename T >
class Foo< T, typename enable_if< std::tr1::is_integral< T >::value, IntegralTypeTag >::type >
{
    static void foo( T const& )
    {
        std::cout << "This is the integral partial-specialization class implementation.\n";
    }
};

template< typename T >
class Foo< T, typename enable_if< std::tr1::is_floating_point< T >::value, FloatingPointTypeTag >::type >
{
    static void foo( T const& )
    {
        std::cout << "This is the floating-point partial-specialization class implementation.\n";
    }
};

template< typename T >
inline void
partial_specialization_class_foo( T const& arg )
{
    Foo< T >::foo( arg );
}

void partial_specialization_class_example()
{
    partial_specialization_class_foo( int() );
    partial_specialization_class_foo( float() );
}

:実際のコードでは、 static-methodsに加えてbarbazなどがあります。foo

参考までに、これはC++03です。

余談ですが、私は従来の方法でテンプレート関数のオーバーロードを行っていますか?

4

3 に答える 3

2

ボーンの正解を観察した後、私はそれをもっと単純化したかった。タグと余分なトレイトクラスの使用を削除して、次の構造を考え出すことができました。

template< typename T, typename U = T >
struct Foo
{
};

template< typename T >
struct Foo< T, typename enable_if< std::tr1::is_integral< T >::value, T >::type >
{
    static void foo( T const& )
    {
        std::cout << "This is the integral partial-specialization class implementation.\n";
    }
};

template< typename T >
struct Foo< T, typename enable_if< std::tr1::is_floating_point< T >::value, T >::type >
{
    static void foo( T const& )
    {
        std::cout << "This is the floating-point partial-specialization class implementation.\n";
    }
};

template< typename T >
inline void
partial_specialization_class_foo( T const& arg )
{
    Foo< T >::foo( arg );
}

void partial_specialization_class_example()
{
    partial_specialization_class_foo( int() );
    partial_specialization_class_foo( float() );
}

これは、クラスに2つのテンプレートタイプのパラメーターを提供することで機能すると思います。2番目のパラメーターはコンパイル時の条件付きです。

  • これはデフォルトで最初のパラメーターと同じであるため、呼び出し元は最初のパラメーターのみに焦点を合わせます。
  • 最初のテンプレートパラメータと同じ2番目のテンプレートパラメータを持つ部分スペシャライゼーションのみを一致させることができます。
  • 失敗するenable_ifと、部分的な特殊化全体を照合することができなくなります。

比較的理解しにくいと思います。

于 2013-02-27T16:30:30.750 に答える
2

これが1つのアプローチです:

#include <tr1/type_traits>
#include <iostream>

struct IntegralTypeTag;
struct FloatingPointTypeTag;

template <
  typename T,
  bool is_integral = std::tr1::is_integral<T>::value,
  bool is_floating_point = std::tr1::is_floating_point<T>::value
> struct TypeTag;

template <typename T>
struct TypeTag<T,true,false> {
  typedef IntegralTypeTag Type;
};

template <typename T>
struct TypeTag<T,false,true> {
  typedef FloatingPointTypeTag Type;
};

template <typename T,typename TypeTag = typename TypeTag<T>::Type> struct Foo;


template <typename T>
struct Foo<T,IntegralTypeTag> {
  static void foo( T const& )
  {
    std::cout << "This is the integral partial-specialization class implementation.\n";
  }
};

template <typename T>
struct Foo<T,FloatingPointTypeTag> {
  static void foo( T const& )
  {
    std::cout << "This is the floating-point partial-specialization class implementation.\n";
  }
};

template< typename T >
inline void
partial_specialization_class_foo( T const& arg )
{
      Foo< T >::foo( arg );
}

int main(int,char**)
{
  partial_specialization_class_foo(int());
  partial_specialization_class_foo(float());
  return 0;
}
于 2013-02-27T15:20:55.490 に答える
0

IntegralTypeTagenable_if邪魔になります。の2番目のパラメータのデフォルトFoovoid、と同じではないIntegralTypeTagため、の特殊化Fooは一致しません。

つまり、Foo< int, void >(これはあなたが行うときに得られるものです)は、あなたの意図した専門分野(ロジックの後)とFoo<int>一致しません。Foo< int, IntegralTypeTag >intenable_if

タグ付けはクラスの結果であり、type_traits他のクラスを単純化するために使用できtype_traitsます。

于 2013-02-27T15:18:44.047 に答える