Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I force template parameter type to be signed?

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?

like image 507
feelfree Avatar asked Jun 15 '17 08:06

feelfree


People also ask

Can template have default parameters?

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

How will you restrict the template for a specific datatype?

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.

Can we pass Nontype parameters to templates?

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.

Can a template parameter be a function?

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.


1 Answers

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.

like image 89
alexeykuzmin0 Avatar answered Sep 22 '22 06:09

alexeykuzmin0