SFINAE 用于无符号类型选择

Posted

技术标签:

【中文标题】SFINAE 用于无符号类型选择【英文标题】:SFINAE for unsigned type selection 【发布时间】:2021-09-29 21:22:10 【问题描述】:

我正在尝试使用 SFINAE 来检查一个类型是否具有 unsigned 等效项。虽然它似乎对intbool 有效,但它对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;
      |           ^~~~~~~~~~~~~~~~~~~~~~~~

【问题讨论】:

【参考方案1】:

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

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

来自std::make_unsigned

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

如果Tsignedunsigned char, short, int, long, long long;提供了此列表中对应于Tunsigned 类型。

如果T 是枚举类型或charwchar_tchar8_t(C++20 起)、char16_tchar32_t;提供具有与T 相同的sizeof 的最小秩的unsigned 整数类型。

否则,行为未定义。 (直到 C++20) 否则,程序格式错误。 (C++20 起)

【讨论】:

如果程序格式不正确,SFINAE是否应该不启动并使用其他重载? @user3882729 from cppreference.com "只有函数类型或其模板参数类型或其显式说明符 (C++20 起)的直接上下文中的类型和表达式中的失败是 SFINAE 错误。”我认为这就是这里的问题。 make_unsigned&lt;float&gt; 可以解决,错误发生在它的实例化中。 (我可能使用了不正确的术语,但我希望你能明白我的意思)。

以上是关于SFINAE 用于无符号类型选择的主要内容,如果未能解决你的问题,请参考以下文章

java数据类型是有符号的,那与有些无符号的如何区别

用于包装无符号二进制数据的 SWIG 技术

C之有符号与无符号

带无符号整数的 QSpinBox 用于十六进制输入

Mysql数据类型

mysql 常用字段类型