user283474
user283474

Reputation: 75

C++ template specialization by type groups combined with basic type

I would like to specialize template by group of types and also by extra definition for some specific simple types. Is it in C++11 and boost 1.60 possible? Following pseudocode illustrates my intention:

template <typename T> // Universal definition
struct convert
{  ...  }

template <> /* Definition for integral types like defined by std::type_traits */
struct convert<integral_types>
{  ...  }

template <> /* Definition for floating point types like defined by type_traits */
struct convert<floating_types>
{  ...  }

template <> /* Exception from integral types - specific definition */
struct convert<char>
{  ...  }

I think this could be solved by tag dispatcher, but I'm not sure if it's best solution. Another option is enable_if, combined with is_integral (and similar groups) , but simple char type is problem...

Upvotes: 5

Views: 632

Answers (2)

Ralf
Ralf

Reputation: 1295

Here is an alternative solution without using std::enable_if_t:

// g++ -Wall -std=c++11 -o typetraitstest typetraitstest.C

#include <iostream>
#include <type_traits>
#include <cstdint>

template <typename T, bool isFloatingPoint, bool isSigned>
struct _Numeric;

template <typename T>
struct _Numeric<T, true, true>
{
  void doit() { std::cout << "FloatingPoint " << sizeof (T) << " byte\n"; }
};

template <typename T>
struct _Numeric<T, false, true>
{
  void doit() { std::cout << "SignedInt " << sizeof(T) << " byte\n"; }
};

template <typename T>
struct _Numeric<T, false, false>
{
  void doit() { std::cout << "UnsignedInt " << sizeof(T) << " byte\n";  } 
};

template <>
struct _Numeric<char, false, true>
{
  void doit() { std::cout << "special case char\n"; }
};

template <typename T>
struct Numeric :
  _Numeric<T, std::is_floating_point<T>::value, std::is_signed<T>::value>
{};
  
int
main()
{
  Numeric<float> f;
  Numeric<int32_t> i32;
  Numeric<uint64_t> u64;
  Numeric<char> c;
  
  f.doit();
  i32.doit();
  u64.doit();
  c.doit();
  return 0;
}

This is the output (note that char seems to be signed):

% ./typetraitstest
FloatingPoint 4 byte
SignedInt 4 byte
UnsignedInt 8 byte
special case char

Upvotes: 0

Jarod42
Jarod42

Reputation: 217283

You may do something like:

template <typename T, typename Enabler = void> // Universal definition
struct convert
{  ...  };

template <typename T> /* Definition for integral types like defined by std::type_traits */
struct convert<T, std::enable_if_t<std::is_integral<T>::value>>
{  ...  };

template <> /* Exception from integral types - specific definition */
struct convert<char, void>
{  ...  };

Upvotes: 9

Related Questions