4

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?

6
  • 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). Commented Sep 14, 2019 at 6:43
  • fyi it’s the this pointer that’s used for member function calls, not the implicit object parameter. coliru.stacked-crooked.com/a/3819152edc5a1914 Commented Sep 14, 2019 at 6:47
  • @Darklighter guess your code only goes to show that *this is always lvalue? Commented Sep 14, 2019 at 6: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. Commented Sep 14, 2019 at 7:03
  • @Darklighter First form uses implied object argument which is the same as (*this). Commented Sep 14, 2019 at 7:18

2 Answers 2

3

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).

Sign up to request clarification or add additional context in comments.

4 Comments

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 I agree, the implicit object parameter is only important during overload resolution to build up complete function signatures.
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 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.
2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.