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 &lt;typename T&gt; concept arithmetic = std::integral&lt;T&gt; || std::floating_point&lt;T&gt;;),但在我看来,这样的基本概念应该在标准库中定义。它不存在有什么好的理由吗?或者有没有建议添加?

【问题讨论】:

似乎是一个疏忽,因为std::is_arithmetic 存在。您可以使用它来编写自己的概念。 通过这种思维方式,我们可以说我们不需要任何概念,因为在 标头中定义的大多数概念在 中都有它们的integral_constant 版本,有些甚至是使用它们实现的。但是integral_constant和一个概念是完全不同的东西,integral_constant不能作为模板参数列表中的概念。 加上定义算术概念std::is_arithmetic_v而不是概念std::integralstd:floating_point将导致编译器不将这些概念视为算术概念的更受约束的版本。描述于C++ reference 抱歉编辑,这是一个错误。某事某事,概念应该有自己的案例,某事某事。 【参考方案1】:

它不存在有什么好的理由吗?或者有没有建议添加?

没有任何添加它的提议,但我希望看到只提议 template &lt;typename T&gt; concept arithmetic = std::is_arithmetic_v&lt;T&gt;; 的 NB 评论(这并不能保证 C++20 会有这个概念,只是至少会考虑)。

标准库概念是由 Ranges 提案添加的,并由某些概念的算法需求驱动。 integral 出现了很多,但我猜 arithmetic 从来没有出现过,所以它从来没有被添加。例如,如果您查看 N4382(从 2015 年初开始),您可以看到 Integral(以及 SignedIntegralUnsignedIntegral)从一开始就在那里......而即使是 FloatingPoint之后。 (P0631,2019 年 7 月……甚至添加浮点概念的论文也没有提及arithmetic


当然,然后你会遇到一个有趣的问题,即它是否应该严格基于该类型特征还是应该是 template &lt;typename T&gt; concept arithmetic = integral&lt;T&gt; || floating_point&lt;T&gt;; 以便 integralfloating_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++标准库中会有算术类型的概念吗?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C++ 标准库中没有线程池?

为啥 C++ 标准库中没有 SIMD 功能?

c++ 标准库函数都有哪些?

标准库中没有 std::identity 有啥原因吗?

为啥C++标准库中没有transform_if?

c和c++如何把一个整数转化为string