I'll use the following example to illustrate my question:
template<typename T> T diff(T a, T b) { return a-b; }
I expect this template function works only when the type T is signed. The only solution I can figure out is to use delete keyword for all the unsigned types:
template<> unsigned char diff(unsigned char,unsigned char) == delete; template<> unsigned char diff(unsigned char,unsigned char) == delete;
Are there other solutions?
You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
Template non-type arguments in C++It is also possible to use non-type arguments (basic/derived data types) i.e., in addition to the type argument T, it can also use other arguments such as strings, function names, constant expressions, and built-in data types.
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
You can use std::is_signed
together with std::enable_if
:
template<typename T> T diff(T a, T b); template<typename T> std::enable_if_t<std::is_signed<T>::value, T> diff(T a, T b) { return a - b; }
Here std::is_signed<T>::value
is true
if and only if T
is signed (BTW, it is also true
for floating-point types, if you don't need it, consider combining with std::is_integral
).
std::enable_if_t<Test, Type>
is the same as std::enable_if<Test, Type>::type
. std::enable_if<Test, Type>
is defined as an empty struct in case Test
is false and as a struct with an only typedef type
equal to template parameter Type
otherwise.
So, for signed types, std::enable_if_t<std::is_signed<T>::value, T>
is equal to T
, while for unsigned it's not defined and compiler uses SFINAE rule, so, if you need to specify an implementation for a particular non-signed type, you can easily do that:
template<> unsigned diff(unsigned, unsigned) { return 0u; }
Some relevant links: enable_if, is_signed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With