考虑下列方案:
#include <iostream>
template <typename T>
void foo(const T* x) {
x();
}
void bar() { std::cout<<"bar() is called\n"; }
int main() {
foo(bar);
}它在clang++ & VC++上编译得很好,但是g++给出了以下编译器错误(参见live 这里 )
main.cpp: In function 'int main()':
main.cpp:10:9: error: no matching function for call to 'foo(void (&)())'
foo(bar);
^
main.cpp:3:6: note: candidate: template<class T> void foo(const T*)
void foo(const T* x) {
^~~
main.cpp:3:6: note: template argument deduction/substitution failed:
main.cpp:10:9: note: types 'const T' and 'void()' have incompatible cv-qualifiers
foo(bar);
^我在使用g++ & clang++时使用了g++,在使用VC++编译器时使用了/W4 &/Za选项。参见现场演示这里 & 这里。那么,我想知道模板类型参数T是如何推导出来的呢?如果我从程序中删除const,那么它在g++上也会编译得很好。如果我使用const T&,那么它在所有三个编译器上都编译得很好。那么,在这些情况下,如何精确地推导出类型呢?
更新:
此程序在Intel C++编译器上也无法编译。参见现场演示这里。那么,这是g++ & Intel C++中的bug,还是Clang++ & VC++中的bug?
发布于 2018-03-15 10:34:20
这本质上是CWG第1584期
尚不清楚以下内容是否格式良好: void (){}模板void (const*){} int main() { deduce(foo);} 在此示例中,实现的处理各不相同。
目前仍处于活动状态。要说哪个编译器是正确的是不可能的。虽然正如2015年的说明所示,工作组目前的共识是,应拒绝这一点。
为了提供更多的上下文,我们必须记住,带有cv-限定符-seq的函数类型具有特殊的意义(考虑成员函数),而不仅仅是一种类型,它指定了一些不能修改的内容。此外,您甚至不能以某种鬼鬼祟祟的方式添加cv限定,正如[dcl.fct]/7所说明的:
cv-限定符-seq在函数声明器中的作用与在函数类型的顶部添加cv限定不一样。在后一种情况下,cv-限定符将被忽略。 注释:具有cv-限定符-seq的函数类型不是cv限定类型;没有cv限定函数类型。- end注意事项
在该语言中无法形成const限定函数类型。然而,我们需要的推论是将const T推导为void()。前者是const限定类型,也必须是函数类型。但那是一种不存在的类型!那么怎么推断呢?!
另一方面,如果您使用的是引用而不是指针,那么标准中就有推断它的机器。
所以现在还不清楚该如何解决这一问题。一方面,今天的措辞不允许它本身,但另一方面,它的机器已经到位,以供参考。因此,有些实现会对指针执行同样的操作。
https://stackoverflow.com/questions/49295709
复制相似问题