为什么较新的编译器开始接受这个模板函数调用?

5
下面这个涉及调用模板函数 std::atomic_fetch_add() 的小型 C++ 程序,在 x86-64 clang 版本低于 9.0 和 gcc 版本低于 9.1 的 godbolt 编译器中无法编译,两种情况都使用了 --std=c++11 选项。
#include <iostream>
#include <atomic>

std::atomic<char> ch ('@');

int main ()
{
    std::atomic_fetch_add (&ch, 5);
    std::cout << ch << std::endl;
}

在那些早期的编译器版本中(可能更与编译器提供的C++库相关,我不确定),std::atomic_fetch_add(&ch, 5); 调用无法匹配到任何原子获取函数的模板特化,因为ch的类型是char,而5的类型是int
: 在函数'main'中: :8:34: 错误:没有找到可调用的 'atomic_fetch_add' 函数来匹配参数类型(std::atomic*, int) std::atomic_fetch_add(&ch, 5); ...
然而,之后的编译器版本(和库?)成功地编译了这种用法。
  1. 是什么改变使得它开始编译?
  2. 如果这是一个标准库的改变,使用了什么技术来实现这个?
  3. C++标准(以及哪个版本?)是否要求这种用法应该起作用?
我基本上是一个C++初学者,但我了解到这与隐式转换在确定适当的模板特化时没有被执行有关。(可能我没有使用准确的语言。)
我知道我可以通过将调用重写为以下两种方式之一来使其工作:
std::atomic_fetch_add<char> (&ch, 5);

或者

std::atomic_fetch_add (&ch, (char)5);

然而,我对获取支持无显式实例化和无转换的 <atomic> 库版本很感兴趣。(编译器是clang 15.0.0,--std=c++11。该库是Dinkum库的专有版本。)

我需要了解如何支持调用模板函数,比如 std::atomic_fetch_char (&ch, 5),其中参数类型与模板声明中的不完全匹配。例如,我想了解在Linux /usr/include/c++/11/ 标准库中是如何支持这一点的。

我自己提出的最接近的方案是,添加各种 std::atomic_fetch_add() 和类似函数的非模板重载实例,但我没有看到在Linux/GNU C++库中这样做,我怀疑是否存在更简洁的方法。我想要理解它。


3
由于缺陷报告P0558R1,C++11标准中的 std::atomic_fetch_add 的行为已经被追溯性地更改。 - Some programmer dude
1个回答

6

std::atomic_fetch_add原本要求第二个参数与原子对象的value_type类型相同,因为两个参数都参与类型推断。

但这在缺陷报告P0558R1中被移除了,现在只有原子对象参与类型推断,第二个参数仅转换为原子对象的differece_type类型。

您会收到错误提示,是因为旧版本没有修复此缺陷报告,而新版本已经修复了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接