在related question中,它表示没有指向非成员const函数的指针。另外,C ++ 11 8.3.5 / 6说
cv-qualifier-seq在函数声明符中的作用与在函数类型之上添加cv-qualification不同。在后一种情况下,cv限定符是 忽略。 [注意:具有cv-qualifier-seq的函数类型不是cv限定类型; 没有符合cv标准的函数类型。 - 后注]
如果我理解正确,这意味着没有非成员const函数。 (虽然这些函数不是常量,但不能按照3.10 / 6进行修改)。特别是,指向const函数的指针是没有意义的。
但是,似乎有些编译器会在类型推导上下文中创建指向const函数的指针。例如,考虑代码:
#include <iostream>
void f() {}
template <typename T> void g( T*) { std::cout << "non const" << std::endl; }
template <typename T> void g(const T*) { std::cout << "const " << std::endl; }
int main() {
g(f);
}
当使用GCC和Intel编译时,代码输出“非常量”,正如我从上面的引用中所期望的那样。但是,使用Clang和Visual Studio编译时输出为“const”。
我的解释是否正确?
更新
在评论之后,我试图澄清我不谈论const成员函数。我对非成员函数感兴趣(但同样的参数也可能适用于非静态成员函数)。我也改变了问题标题,使其更精确。
与上述g(f)
的解决方案一致,以下行对于GCC和英特尔来说是非法的,但不适用于Clang和Visual Studio
const auto* ptr = &f;
更新2:
我同意Andy Prowl的解释,并选择了他的答案。但是,在此之后,我意识到这个问题是CWG open issue。
答案 0 :(得分:10)
如果我理解正确,这意味着没有非成员const函数。 (虽然这些函数不是常量,但不能按照3.10 / 6进行修改)。特别是,指向const函数的指针是没有意义的。
是的,没有const
函数这样的东西,并且尝试创建一个忽略,因为你引用了相同的段落。这很重要,因为无论如何创建const
函数类型的程序不格式不正确(as was the case in C++03);简单地说,它的尝试被忽略了,而是考虑了非const
函数类型。
这可能是GCC和ICC无法应用的原因,因为当删除非const
重载时,the program does not compile:
#include <iostream>
void f() {}
template <typename T> void g( T const*)
{
std::cout << "const " << std::endl;
}
int main() {
g(f); // ERROR with GCC and ICC, compiles with Clang
}
关于你的解释:
当使用GCC和Intel编译时,代码输出“非常量”,正如我从上面的引用中所期望的那样。但是,使用Clang和Visual Studio编译时输出为“const”。我的解释是否正确?
我不相信。据我所知, Clang是对的。
这个结论是基于两个函数模板都可行的事实,因为const
限定符在函数类型上被忽略,而一个比另一个更专业。
根据C ++ 11标准的第8.3.5 / 7段,事实上:
[...] cv-qualifier-seq在函数声明符中的作用与在顶部添加cv-qualification不同 功能类型。 在后一种情况下,忽略cv限定符。 [...]
这有效地使第二个函数模板可用于解析调用(显然是第一个)。但由于两个函数模板都是可行的,关于重载决策的第13.3.3.1节开始发挥作用:
鉴于这些定义,一个可行的函数F1被定义为比另一个可行函数F2更好的函数,如果对于所有参数i,ICSi(F1)不是比ICSi(F2)更差的转换序列,然后强>
- 对于某些参数j,ICSj(F1)是比ICSj(F2)更好的转换序列,或者,如果不是,
- 上下文是用户定义转换的初始化(见8.5,13.3.1.5和13.3.1.6)和 从返回类型F1到目标类型的标准转换序列(即,类型的 正在初始化的实体)是比标准转换序列更好的转换序列 F2的返回类型到目标类型。 [...]或者,如果不是那样,
- F1是非模板函数,F2是函数模板特化,或者,如果不是,
- F1和F2是功能模板专业化,F1的功能模板比F2模板更专业,根据14.5.6.2中描述的偏序规则。
由于第二个函数模板比第一个函数模板更专业,因此应通过重载决策选择第二个函数模板。因此, Clang是对的。