将 const 限定符应用于模板参数时的不同编译器行为

Different compiler behavior when applying a const qualifier to a template argument

本文关键字:编译器 参数 const 应用于      更新时间:2023-10-16

考虑以下示例(godbolt):

#include <iostream>
template <typename T>
const T *as_const(T *p) { return p; }
void f() {}
template <typename T>
void g(T *) { std::cout << "A"; }
template <typename T>
void g(const T *) { std::cout << "B"; }
int main() {
g(as_const(&f));
}

GCC 和 Clang都可以编译它,但生成的可执行文件会产生不同的输出:使用 GCC 打印A编译的版本和用 Clang 打印B编译的版本。

你能解释一下这种差异吗?

更新:正如@VTT所指出的,即使删除as_const也会观察到相同的差异。

您似乎在标准中遇到了尚未解决的缺陷。因此,"哪个编译器是正确的?"的答案目前并不完全清楚。

该问题已向委员会提出并由委员会讨论:

目前尚不清楚以下内容的格式是否正确:

void foo(){}
template<class T>
void deduce(const T*) { }
int main() {
deduce(foo);
}

实现在处理此示例时有所不同。

请参阅 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1584,但提议的决议不是 N4141 或 N4659 的一部分。

请注意,您通常不能有指向const函数类型的指针;如果您认为我引用的示例格式不正确,则 gcc 是正确的。它确实拒绝该示例,并在 OP 中选择非 const 版本作为唯一可行的重载。

如果clang(声称执行拟议的决议)是正确的,否则我不确定。我想一旦委员会用一些我们可以使用的规范性措辞解决了这个问题,我们将不得不重新审视这个讨论。

然而

CWG的共识是参数和参数的cv资格必须匹配,因此应该拒绝原始示例。

(上述问题的注释)似乎表明 GCC 是正确的,该问题将得到解决,有利于其行为。