SFINAE 用于无符号类型选择
Posted
技术标签:
【中文标题】SFINAE 用于无符号类型选择【英文标题】:SFINAE for unsigned type selection 【发布时间】:2021-09-29 21:22:10 【问题描述】:我正在尝试使用 SFINAE
来检查一个类型是否具有 unsigned
等效项。虽然它似乎对int
和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;
| ^~~~~~~~~~~~~~~~~~~~~~~~
【问题讨论】:
【参考方案1】:您在无效类型(见下文)上使用make_unsigned
,这会导致行为未定义或程序格式错误。更好的方法是检查它是否是整数:
std::enable_if_t<std::is_integral_v<T>, bool>
来自std::make_unsigned
:
如果T
是整数(bool
除外)或枚举类型,则提供成员 typedef 类型,它是与 T
对应的无符号整数类型,具有相同的 cv 限定符。
如果T
是signed
或unsigned
char
, short
, int
, long
, long long
;提供了此列表中对应于T
的unsigned
类型。
如果T
是枚举类型或char
、wchar_t
、char8_t
(C++20 起)、char16_t
、char32_t
;提供具有与T
相同的sizeof
的最小秩的unsigned
整数类型。
否则,行为未定义。 (直到 C++20) 否则,程序格式错误。 (C++20 起)
【讨论】:
如果程序格式不正确,SFINAE是否应该不启动并使用其他重载? @user3882729 from cppreference.com "只有函数类型或其模板参数类型或其显式说明符 (C++20 起)的直接上下文中的类型和表达式中的失败是 SFINAE 错误。”我认为这就是这里的问题。make_unsigned<float>
可以解决,错误发生在它的实例化中。 (我可能使用了不正确的术语,但我希望你能明白我的意思)。以上是关于SFINAE 用于无符号类型选择的主要内容,如果未能解决你的问题,请参考以下文章