c++ - Microsoft Visual Studio 是否不正确地定义了类型特征的值?
问题描述
作为我正在为一个项目实现的一些几何函数的一部分,我认为将可以输入库的类型限制为仅几何类型是一个好主意。所以我写了以下结构来帮助解决这个问题:
template<typename T>
struct Geometric {
static_assert(std::is_arithmetic_v<T>, "T Must be Arithmetic!");
static_assert(std::is_same_v<T, std::decay_t<T>>, "Must be raw type!");
};
//...
template<typename T>
struct point2 : Geometic<T> {
//...
};
然后,因为我的库需要使用符合算术类型所有常见约定的自定义类型(至少就本项目而言),我想出了一个简单的解决方案,将这种类型集成到库中,只需添加一个该类型的条目std::is_arithmetic
:
using rational_t = boost::multiprecision::cpp_rational;
template<>
struct std::is_arithmetic<rational_t> : std::true_type {};
using rational_point = point2<rational_t>;
但是,此代码始终产生“T 必须是算术!” 编译时的错误消息。所以我稍微深入研究了微软对这些类型特征的实现,发现了一些我没有预料到的东西: 的派生std::is_arithmetic_v<T>
直接来自其他常量,而不是来自其关联的结构。
//MSVC2019 Code found in 'xtr1common', line# 197
// STRUCT TEMPLATE is_arithmetic
template <class _Ty>
_INLINE_VAR constexpr bool is_arithmetic_v = // determine whether _Ty is an arithmetic type
is_integral_v<_Ty> || is_floating_point_v<_Ty>;
template <class _Ty>
struct is_arithmetic : bool_constant<is_arithmetic_v<_Ty>> {};
当然,这阻碍了我的代码,因为我的专业化is_arithmetic<rational_t>
对is_arithmetic_v<rational_t>
.
它特别阻碍了我,因为我期待专业化反向工作,源自is_arithmetic_v
,is_arithmetic
因为它在CPPReference 的页面上对此类型特征进行了详细说明:
辅助变量模板
template< class T > inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
可能的实施
template< class T > struct is_arithmetic : std::integral_constant<bool, std::is_integral<T>::value || std::is_floating_point<T>::value> {};
那么根据标准,MSVC 对这个特征(以及许多其他特征,似乎遵循类似模式)的定义是否合法,或者这是实现中的错误?如果将来我需要专门化这些常量,这样做的理想方法是什么?
解决方案
似乎不允许专门化来自<type_traits>
(除)的模板:std::common_type
除了.
<type_traits>
_std::common_type
标准的相关部分是:(@NathanOliver 提供)
除非另有说明,否则为本子条款 [meta] 中指定的任何模板添加特化的程序的行为是未定义的。
所以 MSVC 使用的实现是一致的。
经典的解决方法是制作自己的特征(基于标准特征)并专门化它。
template <typename T>
struct IsArithmetic : std::is_arithmetic<T> {};
推荐阅读
- java - Java - 将数组元素与传递的 int 进行比较以查看是否相同时,if 语句失败
- python-3.x - Python3在有互联网连接时运行功能+每x分钟检查一次连接
- java - 如何将 json 文本文件解析为 BasicDBobject
- flutter - 如何更改 Flutter 中的默认字体系列
- javascript - JS 惯用的 alert() 没有搞砸 HTML 渲染
- java - 使用 Docx4j 从 XML 转换为 Docx
- mysql - 试图获得每个州的总约会。在 MySQL 1055 中出现错误
- cassandra - 无法识别的 VM 选项“UseParNewGC”错误:无法创建 Java 虚拟机。同时设置 apache-cassandra-3.11.8
- batch-file - 使用 bat 文件从 1 .txt 中提取内容保存到另一个 .txt
- c# - 为什么我不能引用 ICollection 中的属性?