相关文章推荐
大力的砖头  ·  cypher - How get the ...·  1 年前    · 
含蓄的火腿肠  ·  redux - ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams
  • [...]
  • (4.3) otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access, decltype(e) is the type of the entity named by e . If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed ;
  • [...]
  • For me, the emphasized part both apply to id-expression and class member access , right?

    Playing with my favorite compiler, I get the following.

    ✓ Accepted by the compiler

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

    Ok I guess; N::f is an unparenthesized id-expression and does not name a set of overloaded functions.

    ✗ Rejected by the compiler

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

    Ok; N::f does name a set of overloaded functions.

    ✗ Rejected by the compiler

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

    Hum? S::f would name a set of one overloaded function?

    All in all, is my understanding of [dcl.type]/4.3 just bad? is gcc trunk wrong? both? none? kamoulox?

    The simple reason is that the use of S::f is constrained for class members.

    [expr.prim.id]

    2 An id-expression that denotes a non-static data member or non-static member function of a class can only be used:

  • as part of a class member access in which the object expression refers to the member's class or a class derived from that class, or
  • to form a pointer to member ([expr.unary.op]), or
  • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
  • The last bullet, the one related to your code, only applies to non-static data member. There is no provision for functions.

    I can only speculate as to why it's not allowed, though I previously asked that question.

    It's worth a note that decltype(&S::f) works here as pointer-to-member-function type,
    again unless the f names a set of overloaded (member) functions.

    The function type itself can be extracted from the pointer-to-member-function type.
    If the member function is cv-or-ref qualified then it has an abominable function type.
    The std traits are lacking here - a library like Boost.CallableTraits helps.

    Hi. Thank you for your help. Note though this question is tagged language-lawyer. It generally means we're not looking for a solution or a workaround, but for a reason/a quote from the Standard. – YSC Sep 27, 2018 at 16:47

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.