3

With reference to Non-static member functions, under

const-, volatile-, and ref-qualified member functions

it is mentioned:

A non-static member function can be declared with no ref-qualifier, with an lvalue ref-qualifier (the token & after the parameter list) or the rvalue ref-qualifier (the token && after the parameter list). During overload resolution, non-static cv-qualified member function of class X is treated as follows:

no ref-qualifier: the implicit object parameter has type lvalue reference to cv-qualified X and is additionally allowed to bind rvalue implied object argument

lvalue ref-qualifier: the implicit object parameter has type lvalue reference to cv-qualified X

rvalue ref-qualifier: the implicit object parameter has type rvalue reference to cv-qualified X

Note: unlike cv-qualification, ref-qualification does not change the properties of the this pointer: within a rvalue ref-qualified function, *this remains an lvalue expression.

In this context, what is the difference between the implicit object parameter and *this?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Vinod
  • 925
  • 8
  • 9
  • I picture it as that the rvalue ref qualifier is removed from `*this` once the function is invoked. There probably is some rationale that you shouldn’t be able to call further rvalue qualified functions without an explicit `std::move(*this)`. – Darklighter Sep 14 '19 at 06:43
  • fyi it’s the `this` pointer that’s used for member function calls, not _the implicit object parameter_. http://coliru.stacked-crooked.com/a/3819152edc5a1914 – Darklighter Sep 14 '19 at 06:47
  • @Darklighter guess your code only goes to show that *this is always lvalue? – Vinod Sep 14 '19 at 06:55
  • Yes, it showcases the _Note_ from your quote, but it also showcases that there is no difference between `memfun()` and `(*this).memfun()`, i.e. it’s not like the first form uses the type of _the implicit object paramter_ instead of the type of `*this` for overload resolution. – Darklighter Sep 14 '19 at 07:03
  • @Darklighter First form uses *implied object argument* which is the same as `(*this)`. – user7860670 Sep 14 '19 at 07:18
  • i think the question is answered [here](https://stackoverflow.com/questions/32620750/why-are-rvalues-references-variables-not-rvalue) – Darklighter Sep 14 '19 at 07:20

2 Answers2

2

I think the difference can be illustrated with the following example:

When overload resolution selection relies on CV-qualifier *this will have an appropriate CV qualifier just like an implicit object parameter:

struct t_Tester
{
    constexpr auto Probe(/* t_Tester & param */) { return 1; }
    constexpr auto Probe(/* t_Tester const & param */) const { return 2; }
    constexpr auto Test(/* t_Tester const & param */) const { return (*this).Probe(); }
};

static_assert(2 == t_Tester{}.Test());

However when overload resolution selection relies on rvalue / lvalue reference qualifier *this will be still an lvalue even if implicit object parameter is an rvalue reference and the object itself is an rvalue:

struct t_Tester
{
    constexpr auto Probe(/* t_Tester & param */) & { return 1; }
    constexpr auto Probe(/* t_Tester && param */) && { return 2; }
    constexpr auto Test(/* t_Tester && param */) && { return (*this).Probe(); }
};

static_assert(1 == t_Tester{}.Test());

Note: Invoking function in class scope without using this pointer explicitly (like return Probe();) will use implied object argument (which is the same as (*this)) that should not be confused with implicit object parameter (which is just an invisible part of member function signatures used during overload resolution).

user7860670
  • 35,849
  • 4
  • 58
  • 84
  • But once an rvalue qualified member function is invoked, what effect does the (initial) type of _the implicit object parameter_ have further on? I don’t think it has any. – Darklighter Sep 14 '19 at 07:00
  • 1
    @Darklighter I agree, *the implicit object parameter* is only important during overload resolution to build up complete function signatures. – user7860670 Sep 14 '19 at 07:04
  • I can't see any difference if writing `return (*this).Probe();` vs. `return Probe();`. I can't catch what is now the difference between *this and implicit object pointer. Can you explain a bit? – Klaus Sep 14 '19 at 07:06
  • 1
    @Klaus The construct `return Probe()` uses *implied object argument*, which is the same as `(*this)`. While *implicit object parameter* is an imaginary part of non-static member function signatures. – user7860670 Sep 14 '19 at 07:15
1

ref-qualifiers allow function overloading based on the type of reference of an expression.

Since there are no pointers (or references) to references in C++ this can’t point to a (n rvalue) reference, so *this can’t be an rvalue.

rvalue, lvalue and reference (intentionally) loose their relevance once the function is invoked.

Darklighter
  • 2,082
  • 1
  • 16
  • 21