首页 > 解决方案 > SFINAE 用于无符号类型选择

问题描述

我试图用来SFINAE检查一个类型是否有unsigned等价物。虽然它似乎对intand有效bool,但对float. 从错误来看,似乎没有定义某种类型。问题是如果模板参数enable_if格式不正确,为什么不将其从重载选择中删除?

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

错误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;
      |           ^~~~~~~~~~~~~~~~~~~~~~~~

标签: c++c++11sfinae

解决方案


您正在使用make_unsigned无效类型(见下文),这会使行为未定义或程序格式错误。更好的方法是检查它是否是整数:

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

来自std::make_unsigned

  • 如果T是整数(除了bool)或枚举类型,则提供成员 typedef 类型,它是对应于 的无符号整数类型T,具有相同的 cv 限定符。

  • 如果Tsigned, unsigned char, short, int, ; long_ 提供了此列表中对应long long的类型。unsignedT

  • IfT是枚举类型或char, wchar_t, char8_t(C++20 起), char16_t, char32_t; unsigned提供具有相同等级的最小sizeof整数类型T

否则,行为未定义。(C++20 前)
否则,程序是非良构的。(C++20 起)


推荐阅读