考虑以下示例(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
被删除,也会发现相同的差异。
答案 0 :(得分:17)
您似乎遇到了标准中尚未解决的缺陷。那么“哪个编译器是对的?”的答案。目前还不完全清楚。
委员会提出并讨论了这个问题:
目前尚不清楚以下是否格式良好:
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(claims to implement the proposed resolution)不对,我不确定。我想,一旦委员会用我们可以使用的一些规范性措辞解决了这个问题,我们就必须重新讨论这个问题。
然而,
CWG的共识是参数和参数的cv限定必须匹配,因此原始示例应该被拒绝。
(注意上述问题)似乎表明gcc是对的,问题将得到解决,有利于其行为。