1

I know that const and volatile are mentioned in the C++ specification as the "cv-qualifiers", like [basic.type.qualifier].

Now I have this code (godbolt) which doesn't compile.

#include <string>
class Dummy
{
    std::string member{"test"};

    public:
    std::string const && foo() &&
    { return std::move(member); }
};

int main()
{
    Dummy d;
    std::string s = d.foo();
}

It doesn't compile because w is an LValue and foo() only exists for RValues. That's fine and expected.

But let's have a look at the error message:

<source>: In function 'int main()':
<source>:14:26: error: passing 'Dummy' as 'this' argument discards qualifiers [-fpermissive]
   14 |     std::string s = d.foo();
      |                     ~~~~~^~
<source>:7:26: note:   in call to 'const std::string&& Dummy::foo() &&'
    7 |     std::string const && foo() &&
      |   

The error message says "discards qualifiers". Thus my question: is && considered a qualifier, too? If it's not a qualifier, what is it then?

I can understand that the compiler would need to drop && to & or to nothing in order to make it compile. So yes, it needs to discard something. But what exactly is it that it would need to drop?

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • 2
    With `std::string const && foo() &&` the last `&&` says this function is only usable with rvalues. `d` is not an rvalue so it can't call `foo`. – NathanOliver Jul 07 '23 at 12:28
  • related/dupe: https://stackoverflow.com/questions/8610571/what-is-rvalue-reference-for-this – NathanOliver Jul 07 '23 at 12:29
  • [Member_functions_with_ref-qualifier](https://en.cppreference.com/w/cpp/language/member_functions#Member_functions_with_ref-qualifier) – Jarod42 Jul 07 '23 at 12:33
  • @ThomasWeller Also see: https://stackoverflow.com/a/55959119/4342498 – NathanOliver Jul 07 '23 at 12:37
  • 1
    @NathanOliver-IsonStrike thanks for pointing out my mistake. – Mark Ransom Jul 07 '23 at 13:14
  • Unrelated, but returning `std::string const &&` makes little sense. You'll have a copy of `member`, although the intention probably is to have a move. – Evg Jul 07 '23 at 13:36
  • @NathanOliver-IsonStrike: In the question I stated "It doesn't compile because w is an LValue and foo() only exists for RValues. That's fine and expected." I know that it doesn't compile and I understand why it doesn't compile. I just need it not to compile in order to get an error message. So, your first proposed link is not a dupe. – Thomas Weller Jul 07 '23 at 13:59
  • Sorry everyone for not responding in a timely manner. I was in a meeting. – Thomas Weller Jul 07 '23 at 13:59
  • @EvgsupportsModeratorStrike: yes, it doesn't make sense. That's the point I'm trying to make with my team members. I should have left that const out in the MRE though. The complete code will show where copies and moves are made and that const prevents optimization. – Thomas Weller Jul 07 '23 at 14:03

1 Answers1

5

It's a qualifier. The quote you refer to is about types, but the qualifier that is dropped here is that of a member function.

Not sure if there is a better quote, though it mentions the terms in context at least: class.mfct.non.static

[Note 2: An implicit object member function can be declared with cv-qualifiers, which affect the type of the this pointer ([expr.prim.this]), and/or a ref-qualifier ([dcl.fct]); both affect overload resolution ([over.match.funcs]) — end note]

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 2
    [N2439](https://wg21.link/N2439) is the proposal that adds ref-qualifiers to the language, since C++11. – Dr. Gut Jul 07 '23 at 12:49
  • **ref-qualifier**, that's it. Maybe you want to link [dcl.fct] and [dcl.decl.general], especially https://eel.is/c++draft/dcl.decl.general#nt:ref-qualifier – Thomas Weller Jul 07 '23 at 14:09