Как преобразовать перегруженные шаблонные функции в статические методы частично специализированного шаблонного класса?

У меня есть несколько функций, которые я хочу специализировать на основе качеств типов, таких как «символ, целое число со знаком, целое число без знака, с плавающей точкой, указатель»; использование 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() );
}

кроме моего реального кода, у меня также есть bar,bazи т. д. вместе с 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() );
}

Заметка: в моем реальном коде я бы bar,bazи т. д. вместе с foo статическая-метода.

К вашему сведению, это C ++ 03.

Кроме того, я делаю перегрузку шаблонной функции обычным способом?

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

Я думаю, что это работает, предоставляя два параметра типа шаблона для класса, где второй является условным во время компиляции:

  • По умолчанию он совпадает с первым параметром, поэтому вызывающая сторона фокусируется только на первом параметре.
  • Только частичные специализации, которые имеют тот же второй параметр шаблона, что и первый, могут быть сопоставлены.
  • когда enable_if терпит неудачу, вся частичная специализация недоступна для сравнения.

Я нахожу это менее громоздким для понимания, сравнительно.

2

IntegralTypeTag в enable_if будет мешать. По умолчанию для второго параметра Foo является void, который не совпадает с IntegralTypeTagтак что специализация Foo не сможет соответствовать.

То есть, Foo< int, void > (что вы получаете, когда делаете Foo<int>) не совпадает Foo< int, IntegralTypeTag >, который вы хотели int специализация есть (после enable_if логика).

Пометка является результатом type_traits класс, который вы можете использовать для упрощения других type_traits классы.

0
По вопросам рекламы [email protected]