如何将模板化函数重载转换为部分专用模板类静态方法?

时间:2013-02-27 14:52:34

标签: c++ templates static-methods sfinae partial-specialization

我想根据类型质量专门设置几个函数,例如“字符,有符号整数,无符号整数,浮点数,指针”;使用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

但是,我想将每个质量的所有这些函数分组为一个模板化的类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() );
}

注意:在我的真实代码中,我有barbaz等,以及foo静态方法。

仅供参考,这是C ++ 03。

顺便说一句,我是否以常规方式进行模板化函数重载?

3 个答案:

答案 0 :(得分:2)

这是一种方法:

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

答案 1 :(得分:2)

在观察了Vaughn的正确答案之后,我想更多地简化它。我能够删除使用标签和额外特征类来提出以下结构:

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

我认为这可以通过向类提供两个模板类型参数来实现,其中第二个是编译时条件:

  • 此默认设置与第一个参数相同,因此调用者只关注第一个参数。
  • 只能匹配与第一个模板参数相同的第二个模板参数的部分特化。
  • enable_if失败时,整个部分专业化无法与之匹配。

相对而言,我觉得理解起来不那么麻烦。

答案 2 :(得分:0)

IntegralTypeTag中的

enable_if会妨碍您。 Foo的第二个参数的默认值为void,与IntegralTypeTag不同,因此Foo的特化将无法匹配。

即,Foo< int, void >(这是您Foo<int>时得到的)与您Foo< int, IntegralTypeTag >专业化所需的int不匹配({{1}之后逻辑)。

标记是enable_if类的结果,您可以使用它来简化其他type_traits类。