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

vit*_*aut 27 c++ gcc templates const clang

考虑以下示例(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));
}
Run Code Online (Sandbox Code Playgroud)

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

你能解释一下这个区别吗?

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

Bau*_*gen 17

您似乎遇到了标准中尚未解决的缺陷.那么"哪个编译器是对的?"的答案.目前还不完全清楚.

委员会提出并讨论了这个问题:

目前尚不清楚以下是否形成良好:

void foo(){}

template<class T>
void deduce(const T*) { }

int main() {
  deduce(foo);
}
Run Code Online (Sandbox Code Playgroud)

实施方案对这个例子的处理方式各不相同.

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

请注意,您通常不能指向const函数类型; 如果你考虑我引用格式错误的例子,gcc就是正确的.它确实拒绝了这个例子,在OP中,选择非const版本作为唯一可行的重载.

如果clang(声称执行提议的决议)是正确的,我不确定.我想,一旦委员会用我们可以使用的一些规范性措辞解决了这个问题,我们就必须重新讨论这个讨论.

然而,

CWG的共识是参数和参数的cv限定必须匹配,因此原始示例应该被拒绝.

(注意上述问题)似乎表明gcc是正确的,问题将得到解决,有利于其行为.