const forwarding reference gives error C2440: 'initializing': cannot convert from 'const std::string' to 'const std::string &&'
Asked Answered
T

1

6

The following gives a compiler error:

  #include <string>

  const std::string& get_name();

  int main(){
    auto&& name1 = get_name();//should bind to whatever
    const auto& name2 = get_name();//also ok
    const auto&& name3 = get_name();//<-not ok, why ?
    return 0;
  }

Link to godbolt: https://godbolt.org/z/l6IQQ7

If I use const auto& it compiles - but that will not bind to value. auto&& will be bind to anything so that naturally works as well. However, what is the logic behind const auto&& not binding in this case ? I know auto&& will preserve the constness - but is there a way to be const explicit and at the same time be reference/value agnostic ?

Motivation:

For 'normal programming work' inside functions etc. it would be great to be able to say something like: "I do not care if it's a value or reference - but I do not change it for the rest of the function".

This should be possible given current language.

Related question: Why adding `const` makes the universal reference as rvalue

Torras answered 9/10, 2019 at 7:45 Comment(6)
A duplicate? This question asks about template type deduction, but as the rules are identical to auto in this case, I think we can close it?Femme
@Femme I did see that actually- It's not framed the same - also Im asking for a 'solution'Torras
a 'solution' is to just use const auto&. it binds to everything. and you wont get any advantage if you somehow get a const rvalue refEmaciated
@phön ty, thats a bit surprising though, please write an answer with explaination.Torras
@phön I mean, intuitively you would think a returned value into 'const reference' like that would be destructed after that statement.Torras
@Torras yes. but thats lifetime extention. you get it for rvalue refs and const lvalue refs. en.cppreference.com/w/cpp/language/…Emaciated
L
5

For 'normal programming work' inside functions etc. it would be great to be able to say something like: "I do not care if it's a value or reference - but I do not change it for the rest of the function".

You already have the solution at hand for your motivation: use const auto&. const auto& will bind to:

  • const lvalue refs
  • lvalue refs
  • const rvalue refs
  • rvalue refs
  • Additionally, it will extend the lifetime of returned values

So you got everything you need. Yes, it is different from a const rvalue ref, but that wont matter if you just use it, since you wont be able to move from it anyway, since it is const.

Last note: auto&& will always be a reference. its a forwarding reference with deduction, but your final variable will ALWAYS be a reference (rvalue ref or lvalue ref, but never a "value"). Maybe that was/is a misconception?

Lefthanded answered 9/10, 2019 at 8:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.