Home > Mobile >  SFINAE for unsigned type selection
SFINAE for unsigned type selection

Time:09-30

I'm trying to use SFINAE to check if a type has an unsigned equivalent. While it seems to work for int and bool, it fails for float. From the error it seems a certain type is not defined. The question is if the template argument to enable_if is ill-formed, why isn't this removed from overload selection ?

#include <type_traits>
#include <iostream>

template <typename T>
std::enable_if_t<sizeof(std::make_unsigned<T>), bool> hasUnsigned(T x)
{
   return true;
}

bool hasUnsigned(...)
{
   return false;
}

int main()
{
   float x; // If it's int, or char, it below displays true
   std::cout << std::boolalpha << hasUnsigned(x) << std::endl;
}

Error with float

In file included from has_unsigned.cc:1:
/usr/include/c  /10/type_traits: In instantiation of ‘struct std::make_unsigned<float>’:
has_unsigned.cc:5:18:   required by substitution of ‘template<class T> std::enable_if_t<(sizeof (std::make_unsigned<_Tp>) != 0), bool> hasUnsigned(T) [with T = float]’
has_unsigned.cc:18:48:   required from here
/usr/include/c  /10/type_traits:1826:62: error: invalid use of incomplete type ‘class std::__make_unsigned_selector<float, false, false>’
 1826 |     { typedef typename __make_unsigned_selector<_Tp>::__type type; };
      |                                                              ^~~~
/usr/include/c  /10/type_traits:1733:11: note: declaration of ‘class std::__make_unsigned_selector<float, false, false>’
 1733 |     class __make_unsigned_selector;
      |           ^~~~~~~~~~~~~~~~~~~~~~~~

CodePudding user response:

You are using make_unsigned on an invalid type (see below) which makes the behavior undefined or program ill-formed. A better approach would be to check if it's an integer:

std::enable_if_t<std::is_integral_v<T>, bool> 

From std::make_unsigned:

  • If T is an integral (except bool) or enumeration type, provides the member typedef type which is the unsigned integer type corresponding to T, with the same cv-qualifiers.

  • If T is signed or unsigned char, short, int, long, long long; the unsigned type from this list corresponding to T is provided.

  • If T is an enumeration type or char, wchar_t, char8_t (since C 20), char16_t, char32_t; the unsigned integer type with the smallest rank having the same sizeof as T is provided.

Otherwise, the behavior is undefined. (until C 20)
Otherwise, the program is ill-formed. (since C 20)

  • Related