2

I have a template class, the only template parameter is typename.

template<typename T>
class Reader{
    ...
}

Now I want to specialize it for every integer type, something like:

template<typename T - integral>
class Reader{
    //another code
}

How can I achieve this?

RiaD
  • 46,822
  • 11
  • 79
  • 123

3 Answers3

5

You can just an extra defaulted boolean parameter:

template<typename T, bool IsIntegral = std::is_integral<T>::value>
class Reader{ // primary template, used for non-integrals
    ...
}

template<typename T>
class Reader<T, true> { // specialization for integral types
    ...
}
RiaD
  • 46,822
  • 11
  • 79
  • 123
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • Yeah, I forgot to add, that I know about this solution. But I want to be able to add new groups of specialization(i.e floats, strings(wstring, string, char*), and so on) without modification of old code. – RiaD Sep 17 '12 at 21:26
  • 2
    You mean you can't change the `Reader` primary template? If so, you're out of luck. – R. Martinho Fernandes Sep 17 '12 at 21:33
  • It may still be interesting to showcase the usual solution (primary template matching anything, specializations that are partitioned across traits). – Luc Danton Sep 17 '12 at 22:17
3

In similar situations I have used the brute force approach of specializing the class template for all special types. I realize that these are quite a few and that it can become quickly rather painful. However, factoring the interesting members into a base class shared by all specializations works reasonably well. In the cases where I used this approach I typically only had static members in the class, i.e., the fact that constructors are not inherited wasn't a problem (C++ 2011 support a syntax to also inherit constructors but the while point is to keep the notation down):

template <typename T> class Reader { ... };

template <typename T> class IntReader { /* special version for integers */ };
// to bool or not bool?
template <> class Reader<wchar_t>: public IntReader<wchar_t> {};
template <> class Reader<char>: public IntReader<char> {};
template <> class Reader<char16_t>: public IntReader<char16_t> {};
template <> class Reader<char32_t>: public IntReader<char32_t> {};
template <> class Reader<signed char>: public IntReader<signed char> {};
template <> class Reader<signed short>: public IntReader<signed short> {};
template <> class Reader<signed int>: public IntReader<signed int> {};
template <> class Reader<signed long>: public IntReader<signed long> {};
template <> class Reader<signed long long>: public IntReader<signed long long> {};
template <> class Reader<unsigned char>: public IntReader<unsigned char> {};
template <> class Reader<unsigned short>: public IntReader<unsigned short> {};
template <> class Reader<unsigned int>: public IntReader<unsigned int> {};
template <> class Reader<unsigned long>: public IntReader<unsigned long> {};
template <> class Reader<unsigned long long>: public IntReader<unsigned long long> {};

Admittedly, we have too many integer types! Having six different character types is kind of ridiculous.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
2

You can use a dummy std::true_type parameter

template<typename T, typename = std::true_type>
class Reader {

};

template<typename T>
class Reader<T, std::integral_constant<bool, 
                  std::is_integral<T>::value> > {
  // ...
};

Incidentally you will see this pattern used with void instead of true_type, with the specializations often using enable_if and more complicated (and SFINAE involving) conditions.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • can you please give example with `enable_if`? You example works fine, I was tried something with `enable_if` but I get compile error #include template class Name; template class Name::value, int>::type> { }; int main(){ Name name; } – RiaD Sep 19 '12 at 13:51
  • An alternative is to use `typename std::is_integral::type` as the second parameter to match. – Luc Danton Sep 19 '12 at 14:30
  • 1
    @RiaD You need to put `typename` before `std::enable_if`. – Luc Danton Sep 19 '12 at 14:30
  • @Luc Danton, can you please also explain why it's not working with just bool = true and std::is_integral::value – RiaD Sep 19 '12 at 15:02
  • @RiaD I think the restriction is here to make matching specialization (the process at work here) more tractable. Matching `template struct foo {}` is given as an example -- it could get very hard to solve if things of that sort were allowed. – Luc Danton Sep 19 '12 at 15:24
  • @RiaD see http://stackoverflow.com/questions/5978617/why-is-it-disallowed-for-partial-specialization-in-a-non-type-argument-to-use-ne . the committee couldn't explain it technically, so it seems the reason is historical. – Johannes Schaub - litb Sep 22 '12 at 10:50
  • @LucDanton thanks for the `::type` hint. I used to say `::integral_constant` which fails for GCC < 4.5, but didn't know about `::type` :) – Johannes Schaub - litb Sep 22 '12 at 10:53