将 const 限定符应用于模板参数时的不同编译器行为
Different compiler behavior when applying a const qualifier to a template argument
考虑以下示例(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 是正确的,该问题将得到解决,有利于其行为。
相关文章:
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 告诉c++编译器该参数没有别名
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- 推断模板参数的编译器
- 有没有办法在从编译器获取参数时避免预处理器宏?
- 当简单捕获中的标识符显示为参数的声明符 ID 时,没有编译器诊断
- 模板模板参数和模板别名:编译器错误?
- 如果可推导类型上有替换,可变参数模板类型推导会使编译器崩溃
- 如何使用传递给编译器的相同参数在 cmake 中运行命令?
- 编译器是否强制根据模板参数计算表达式?
- C++自定义分配器大小参数作为模板参数会引发编译器错误
- 为什么编译器抱怨 std::thread 参数在转换为右值后必须是可调用的?
- 编译器在C++中调用另一个函数时,在参数中查找已删除的构造函数
- 编译器给出错误:format 指定类型 'float *',但参数的类型'double' [-Wformat]
- 编译器确定参数是给定还是省略
- 当作为参数传入时,是否可以由编译器指定模板类参数?
- 编译器如何处理<Type> <Type> 具有多参数的向量initializer_list
- 模板模板参数导致Clang下的编译器错误,而不是GCC
- 编译器是否C++具有相同模板参数集的每个模板类实例生成代码?