非静态成员函数的十进制类型是否格式错误?

时间:2018-09-26 14:35:12

标签: c++ c++14 language-lawyer c++17 decltype

我不确定是否能完全理解[dcl.type]/4.3

  

对于表达式e,由decltype(e)表示的类型定义如下:

     
      
  • [...]
  •   
  • (4.3)否则,如果e是未括号的id表达式或未括号的类成员访问,则decltype(e)是由e命名的实体的类型。如果没有这样的实体,或者如果e命名了一组重载函数,则程序格式不正确;
  •   
  • [...]
  •   

对我来说,强调的部分都适用于 id-expression 类成员访问权限,对吗?

使用我最喜欢的编译器,我得到以下信息。

✓被编译器接受

namespace N { void f() {} }
using type = decltype(N::f);
type* pf = N::f;

好吧,我猜; N::f是未括号的id表达式,未命名一组重载函数。

✗被编译器拒绝

namespace N { void f() {} void f(int) {} }
using type = decltype(N::f); // error: decltype cannot resolve address of overloaded function
type* pf = N::f;

好吧; N::f确实命名了一组重载函数。

✗被编译器拒绝

struct S { void f(){} };
using type = decltype(S::f); // error: invalid use of non-static member function 'void S::f()'
type* pf = &S::f;

哼? S::f会命名一组重载函数吗?


总而言之,我对[dcl.type]/4.3的理解不好吗? gcc中继错误吗?都?没有?卡穆洛克斯?

2 个答案:

答案 0 :(得分:8)

简单的原因是S::f的使用限制于类成员。

  

[expr.prim.id]

     

2一个id表达式,表示一个非静态数据成员或   类的非静态成员函数只能使用:

     
      
  • 作为类成员访问的一部分,其中对象表达式引用成员的类或从该类派生的类,或者
  •   
  • 形成指向成员([expr.unary.op])的指针,或
  •   
  • 如果该id-expression表示一个非静态数据成员,并且它出现在未评估的操作数中。
  •   

最后一个项目符号(与您的代码相关)仅适用于非静态数据成员。没有功能规定。

我只能推测为什么不允许这样做,though I previously asked that question

答案 1 :(得分:-1)

值得注意的是,decltype(&S::f)在这里用作指向成员函数的指针,
除非f再次命名一组重载(成员)函数。

可以从指向成员函数的指针类型中提取函数类型本身。
如果成员函数是cv-or-ref限定的,则它具有abominable function type
这里缺少std特性-Boost.CallableTraits这样的库有帮助。