3

I want my function to take a lvalue reference and absolutely not a rvalue or temporary or whatever.

This is my function:

template<class T> void foo(T& value) {} // Imagine I have a class Foo struct Foo { int a; int b; }; 

When I call foo(Foo{1, 2}), first, it compiles even if I asked for a lvalue reference, and second, it doesn't work because foo stores the address of the passed value, so I get garbage when I read it later.

How to force foo to take a lvalue reference?

7
  • Look at stackoverflow.com/questions/50852470/… Commented Jun 24, 2020 at 20:28
  • 4
    With your given code snippets foo(Foo(1, 2)) does not compile. Commented Jun 24, 2020 at 20:29
  • 1
    learn.microsoft.com/en-us/cpp/build/reference/… Commented Jun 24, 2020 at 20:29
  • What compiler are you using? VS2019 emits a warning C4239: nonstandard extension used: 'argument': conversion from 'Foo' to 'T &' or an error C2664: 'void foo<Foo>(T &)': cannot convert argument 1 from 'Foo' to 'T &', depending on if languages extensions are enabled or disabled. Commented Jun 24, 2020 at 20:31
  • That doesn't work at all: See on coliru Commented Jun 24, 2020 at 20:31

1 Answer 1

6

First of all, the given code will not compile by default in GCC and Clang, only in MSVC with non-standard extensions.

If you want to make sure that foo() does not accept an rvalue, just delete that overload:

template<class T> void foo(T&& value) = delete; 
Sign up to request clarification or add additional context in comments.

1 Comment

That’s a universal reference, so it triggers regardless of value category. You’re relying on partial ordering to prefer the lvalue-reference choice; better would be to constrain the deleted function template so that it doesn’t outcompete normal functions that require conversions.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.