C++标准库中会有算术类型的概念吗?
Posted
技术标签:
【中文标题】C++标准库中会有算术类型的概念吗?【英文标题】:Will there be a concept for arithmetic types in C++ standard library? 【发布时间】:2020-01-23 19:23:49 【问题描述】:我一直在查看 C++ reference 上的概念库,但找不到算术类型的概念。我在p0898 中也找不到它。我认为这样的概念会很有帮助。 想做的事:
template <typename T>
T some_function(T arg) requires std::integral<T> || std::floating_point<T>
/* functions body */
我可以这样做:
template <std::arithmetic T>
T some_function(T arg)
/* functions body */
我显然可以自己定义它,这并不难(例如template <typename T> concept arithmetic = std::integral<T> || std::floating_point<T>;
),但在我看来,这样的基本概念应该在标准库中定义。它不存在有什么好的理由吗?或者有没有建议添加?
【问题讨论】:
似乎是一个疏忽,因为std::is_arithmetic
存在。您可以使用它来编写自己的概念。
通过这种思维方式,我们可以说我们不需要任何概念,因为在 std::is_arithmetic_v
而不是概念std::integral
和std:floating_point
将导致编译器不将这些概念视为算术概念的更受约束的版本。描述于C++ reference
抱歉编辑,这是一个错误。某事某事,概念应该有自己的案例,某事某事。
【参考方案1】:
它不存在有什么好的理由吗?或者有没有建议添加?
没有任何添加它的提议,但我希望看到只提议 template <typename T> concept arithmetic = std::is_arithmetic_v<T>;
† 的 NB 评论(这并不能保证 C++20 会有这个概念,只是至少会考虑)。
标准库概念是由 Ranges 提案添加的,并由某些概念的算法需求驱动。 integral
出现了很多,但我猜 arithmetic
从来没有出现过,所以它从来没有被添加。例如,如果您查看 N4382(从 2015 年初开始),您可以看到 Integral
(以及 SignedIntegral
和 UnsignedIntegral
)从一开始就在那里......而即使是 FloatingPoint
之后。 (P0631,2019 年 7 月……甚至添加浮点概念的论文也没有提及arithmetic
)
†当然,然后你会遇到一个有趣的问题,即它是否应该严格基于该类型特征还是应该是 template <typename T> concept arithmetic = integral<T> || floating_point<T>;
以便 integral
和 floating_point
概念包含arithmetic
。大概?也许吧?
【讨论】:
【参考方案2】:免责声明:我不是 C++ 专家,对 C++ 概念也不是很熟悉。所以下面的回答
除了应该涵盖整数和浮点类型的示例之外,您没有确切说明该概念应该传达什么。但从更理论、更概念的角度来看,“算术”可以应用得更广泛——尽管算术这个词暗示它是关于数字的。
直觉上,人们可以期待这个概念传达以下内容:
该类型支持基本算术运算+
、-
、*
和/
,这些运算的结果类型与操作数的类型相同。通过快速的网络搜索,这个想法似乎大致如下形式化:
self operator+(self const& x, self const& y);
self operator−(self const& x, self const& y);
self operator∗(self const& x, self const& y);
self operator/(self const& x, self const& y);
但是,正确的算术还需要更多:
给定操作下的元素必须有一个闭包 必须有一个中性的加法元素 (0
)
必须有一个中性的乘法元素 (1
)
每个元素都必须有一个加法逆元 (-x
)
每个元素都必须有一个乘法逆元(/x
- 加法的中性元素除外...)
你看到这里打开了一罐蠕虫。对于整数类型,这些约束已经很难或不可能强制执行,因为可能没有加法逆,特别是对于unsigned
类型。对于浮点类型,由于+/-inf
和最重要的是:NaN
,特殊情况会迅速失控。这一切甚至还没有考虑浮点运算的有限精度。
在理论上的兔子洞更进一步:算术的概念应该是一般代数概念的一种特殊形式(或组合)。例如,将无符号整数类型视为循环group 是完全可以的,并且在某种程度上,一些涉及整数或浮点类型的结构具有与ring 相关联的属性。
因此,一个算术概念,除了说它是“浮点数或整数”之外,肯定会很有趣,但有很多警告。试图清晰地表述这个概念,使其例如也可以应用于复数或类似的结构,是很困难的。 如果有人试图定义这一点,那么肯定也想涵盖其他代数结构,如群或环(例如矩阵或多项式),甚至vector spaces...
至少有人尝试过这个:快速的网络搜索发现Techcnical Report: Fundamental Algebraic Concepts in Concept-Enabled C++ 解决了其中一些想法,包括算术,并指出了与之相关的困难。不过,它是从 2006 年开始的 - 可能会有更新的研究,基于它们进入标准的概念。
【讨论】:
无符号类型的加法逆是完美定义的,与有符号类型不同。乘法逆的要求会自动丢弃整数类型(它们大多是基于 2^n 的,并且 FWIW 标准没有指定确切的基数)。 @bipll 是的,对于 C++ 中通常的无符号类型,加法逆确实是 已定义 (如“not 未定义行为”)由于到(保证的)mod 2^n-行为,但只有 if 指定了“n”(如uint32_t
- unsigned int
不是这种情况)。任何在无符号整数上定义“通用算术”的尝试都只能在大小类型上定义,虽然这可能是可能的,但它的用途可能非常有限,可能违反直觉,而且对于其他(非-整数)类型。以上是关于C++标准库中会有算术类型的概念吗?的主要内容,如果未能解决你的问题,请参考以下文章