函数指针的模板参数推导(g++ & ICC vs Clang++ & VC++)
template argument deduction for function pointer (g++ & ICC vs Clang++ & VC++ )
请考虑以下程序:
#include <iostream>
template <typename T>
void foo(const T* x) {
x();
}
void bar() { std::cout<<"bar() is calledn"; }
int main() {
foo(bar);
}
它在clang++
和VC++
上编译良好,但g++
给出了以下编译器错误(在此处查看现场演示)
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++
时使用了-pedantic-errors
,在使用VC++编译器时使用了/W4
&/Za
选项。在此处和此处查看现场演示。那么,我想知道模板类型参数T将如何在这里推导?如果我从程序中删除const
,那么它也可以在g++
上很好地编译。如果我使用const T&
那么它可以在所有 3 个编译器上编译良好。那么,在这些情况下,这里将如何准确推断类型?
更新:
该程序在英特尔C++编译器上编译时也失败。在此处观看现场演示。那么,这个错误是g++
和英特尔C++中的错误还是Clang++
和VC++中的错误?
这本质上是 CWG 问题 1584:
目前尚不清楚以下内容的格式是否正确:
void foo(){} template<class T> void deduce(const T*) { } int main() { deduce(foo); }
实现在处理此示例时有所不同。
目前仍处于活动状态。实际上不可能说哪个编译器是正确的。尽管正如 2015 年的说明所示,CWG 目前的共识是应该拒绝这样做。
为了提供更多上下文,我们必须记住,具有 cv-qualifier-seq 的函数类型具有特殊含义(想想成员函数),而不仅仅是指定可能无法修改的内容的类型。此外,您甚至不能以某种偷偷摸摸的方式添加简历资格,如 [dcl.fct]/7 所示:
函数声明符中 cv-qualifier-seq 的效果不是 与在函数类型之上添加 CV 资格相同。在 后一种情况,将忽略 CV 限定符。[ 注意:函数类型 具有 CV 限定符序列的不是符合 CV 条件的类型;没有 符合 CV 标准的函数类型。— 尾注 ][ 示例:
typedef void F(); struct S { const F f; // OK: equivalent to: void f(); };
— 结束示例 ]
语言中没有办法形成 const 限定的函数类型。然而,我们需要的推论是将const T
推导为void()
。前者是const 限定类型,也必须是函数类型。但这是一种不可能存在的类型!那么怎么能推断出来呢?!
另一方面,如果您使用参考而不是指针,标准中有机器可以推断它。
因此,目前尚不清楚应该如何解决这个问题。一方面,今天的措辞本身不允许这样做,但另一方面,它的机制已经到位,可供参考。因此,一些实现继续进行并对指针执行相同的操作。
- constexpr 函数的常量引用参数:gcc/msvc vs clang/icc
- 为什么 icc 为简单的主电源生成奇怪的组件?
- JPG-如何从ICC配置文件部分APP2读取/提取数据
- 对clang、gcc和icc中开关枚举类返回的处理一致
- ICC 中的 -O3 会弄乱内联函数,使用 -O1 或 -O2 或相应的手动组装
- ICC 中的 -O2 搞砸了汇编程序,ICC 中的 -O1 和 GCC / Clang 中的所有优化都很好
- 函数指针的模板参数推导(g++ & ICC vs Clang++ & VC++)
- ICC:包括OMP.H需要BytesWap.H
- 英特尔ICC:编译C 代码导致错误
- VS2012 不编译此代码,但 G++、clang 和 ICC 都接受它而无需诊断
- icc崩溃:编译器能在抽象机器中不存在的地方发明写入吗
- 为什么ICC会以这种方式展开此循环并使用LEA进行算术
- 与cmake,icc和pthreads(linux)链接
- 为什么它会在 cilk 中给出分段错误,我正在使用 ICC 编译器
- 幼稚矩阵乘法的优化(ICC与GCC)
- 部分模板专业化和icc
- 如何使用“英特尔C++编译器”(ICC)在三种方法上使用SFINAE
- Clang和GCC与MSVC和ICC的比较:如果复制/移动省略也适用,那么在复制/移动构造函数中是否需要静态断言
- ICC(14.0)甚至无法在Ubuntu 13.10中编译helloworld
- 英特尔 c/c++ 编译器:"could not locate executable icc"(和 ecc)