1

The following code does not compile, expectedly:

struct A {
    void doWork() & {}
};
int main() {
    A{}.doWork();
}

My understanding is that the temporary A{} cannot bind to the &-qualified member function doWork, and this seems in line with this excerpt from cppreference (my italic):

[…] 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 and is not allowed to bind rvalue implied object argument
  • rvalue ref-qualifier: the implicit object parameter has type rvalue reference to cv-qualified X

Also clangd that I use in Vim tells me

'this' argument to member function 'doWork' is an rvalue, but function has non-const lvalue ref-qualifier deleteme.cpp:2:10: note: 'doWork' declared here [member_function_call_bad_ref]

However, when I compile with GCC, I get this error:

$ g++ -std=c++17 deleteme.cpp && ./a.out
deleteme.cpp: In function ‘int main()’:
deleteme.cpp:16:16: error: passing ‘A’ as ‘this’ argument discards qualifiers [-fpermissive]
   16 |     A{}.doWork();
      |                ^
deleteme.cpp:5:10: note:   in call to ‘void A::doWork() &’
    5 |     void doWork() & {
      |          ^~~~~~

which seems not as related to the error as the error from clangd.

On the other hand, I've read those two words, discards qualifiers, when erroneously calling a non-const member function on const object; in such a case I understand the use of "discards", as the object has a const that the function cannot honor, so it should be discarded for things to work.

However, this does not seems to be the case for the code above, where the problem is, I understand, the rvalue-ness of A{} as compared to the lvalue-ness that doWork() & expects.

Is the wording of the error from GCC wrong or am I misreading it?

HighCommander4
  • 50,428
  • 24
  • 122
  • 194
Enlico
  • 23,259
  • 6
  • 48
  • 102
  • Why -1??? Please, explain why, so I edit the question to improve it. – Enlico Nov 05 '20 at 22:10
  • @TonyK, removed, but how could that sting me? Isn't it just innocuous? – Enlico Nov 05 '20 at 22:14
  • 1
    Yes I suppose it is innocuous here. But superfluous semi-colons can certainly cause problems inside a function body. (Also, it makes you look as if you don't know what you are doing.) – TonyK Nov 05 '20 at 22:18
  • Anyway, to answer your question: it seems that gcc treats the `&` as a qualifier, like `const` or `override`. The error message could be more helpful! – TonyK Nov 05 '20 at 22:19
  • 1
    The standard doesn't prescribe the wording of error messages, so there are no right or wrong ones as far as the law is concerned. – n. m. could be an AI Nov 05 '20 at 22:19
  • This is not really a language-lawyer question, since there seems to be no question about the standard text. Also, the "discards qualifiers" diagnostic is correct: ref-qualifiers are qualifiers too, just like const-qualifiers. Are you asking why gcc doesn't specifically say "discards ref-qualifiers"? – cigien Nov 05 '20 at 22:48
  • There are **tons** of wording misuse in the standard itself, and you care about the gibberish compilers puking out... – Language Lawyer Nov 05 '20 at 22:49
  • 1
    @cigien _the "discards qualifiers" diagnostic is correct: ref-qualifiers are qualifiers too_ Except that neither `A{}` nor temporary materialization conversion applied to it have qualifiers. And expressions don't have ref-qualifiers one could discard. – Language Lawyer Nov 05 '20 at 22:51
  • @LanguageLawyer Oh, I interpret it as, the temporary `A{}` having a `&&` qualifier on it. – cigien Nov 05 '20 at 22:53
  • @cigien ppl often confuse "rvalue" with "rvalue reference" :/ Which probably what the author(s) of the diagnostic message did. – Language Lawyer Nov 05 '20 at 22:54
  • @LanguageLawyer Oh, I think I see the issue. Yeah, I'm not using that correctly. Which is probably why the diagnostic made sense to me :p Not a terrible question then. Though I still don't like the language-lawyer tag. – cigien Nov 05 '20 at 22:58
  • @cigien, tag removed. – Enlico Nov 05 '20 at 23:27
  • @cigien, I understand they are all qualifiers, but as I wrote in the question, in case of _non-`const` member function on `const` object_ the qualifiers to be discarded is the one of the object, whereas in the case of the present question, what would that be? Maybe the `&` qualifier of the member function? There's at least a difference in the "direction" (as in, discarding object's qualifier to adapt it to the member function or viceversa). – Enlico Nov 05 '20 at 23:31
  • Actually, I think the diagnostic is not using the terms correctly, but I'm not sure. See LanguagLawyer's response to my first comment. Perhaps they can write an answer explaining the diagnostic. – cigien Nov 05 '20 at 23:38

1 Answers1

1

This is just a case of a suboptimally worded error message in GCC.

My guess would be that in GCC's implementation, diagnosing a mismatch between differing ref-qualifiers shares some code with diagnosing a mismatch between const and non-const, and they reused the same error message.

I would encourage you to file a GCC bug suggesting an improvement to the error message.

HighCommander4
  • 50,428
  • 24
  • 122
  • 194