This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 114a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-04-18


1278. Incorrect treatment of contrived object

Section: 12.2.2.2.2  [over.call.func]     Status: drafting     Submitter: Nikolay Ivchenkov     Date: 2011-03-27

Footnote 127 of 12.2.2.2.2 [over.call.func] paragraph 3 reads,

An implied object argument must be contrived to correspond to the implicit object parameter attributed to member functions during overload resolution. It is not used in the call to the selected function. Since the member functions all have the same implicit object parameter, the contrived object will not be the cause to select or reject a function.

It is not true that “the member functions all have the same implicit object parameter.” This statement does not take into account member functions brought into the class by using-declarations or cv-qualifiers and ref-qualifiers on the non-static member functions:

    struct B
    {
      char f();         // B &
    };

    struct D : B
    {
      using B::f;
      long f();         // D &

      char g() const;   // D const &
      long g();         // D &

      char h() &;       // D &
      long h() &&;      // D &&
    };

    int main()
    {
      // D::f() has better match than B::f()
      decltype(D().f()) *p1 = (long *)0;

      // D::g() has better match than D::g() const
      decltype(D().g()) *p2 = (long *)0;

      // D::h() & is not viable function
      // D::h() && is viable function
      decltype(D().h()) *p3 = (long *)0;
    }

The value category of a contrived object expression is not specified by the rules and, probably, cannot be properly specified in presence of ref-qualifiers, so the statement “the contrived object will not be the cause to select or reject a function” should be normative rather than informative:

    struct X
    {
      static void f(double) {}
      void f(int) & {}
      void f(int) && {}
    };

    int main()
    {
      X::f(0); // ???
    }