1

I have a set of functions where I employ template specialisation to perform transforms on certain values. However, for many types I want to pass the values through unchanged.

To pass a value unchanged I have something like the following function as the default:

template< typename arg >
arg&& convert( arg&& x )
{
    return std::forward<arg>( x );
}

This seems great but according to the answer here it runs the risk of leaving a dangling reference in a statement like:

int&& x = convert( 5 );

If I only use this inline in function arguments, is this risk avoided?

For example, do I run into undefined behaviour if I do something like...

void foo( int&& x )
{
    // Do something with x...
}

foo( convert( 5 ) );
Matt
  • 310
  • 3
  • 10
  • Some context... like why can't you just pass `5` or use `std::move()` – StoryTeller - Unslander Monica Sep 30 '17 at 19:57
  • Say I wanted to write a wrapper for functions that did nothing to most types, but added one to all integers for some reason (this isn't my use case, but let's say it is), then I could use convert for all arguments regardless of type (e.g., in something like a variadic function), and write an integer specialisation for the convert( x ) template that adds one to each integer. – Matt Sep 30 '17 at 20:09
  • Your forwarding code is wrong, it should be `std::forward(x);`. – user7860670 Sep 30 '17 at 20:24
  • So it was, thank you. – Matt Sep 30 '17 at 20:26
  • If you use it as function argument, it's fine. Temporaries are destroyed after the full expression is evaluated. – geza Sep 30 '17 at 20:36

1 Answers1

3

For example, do I run into undefined behaviour if I do something like...

No. The rule, from [class.temporary], emphasis mine, is:

A temporary object bound to a reference parameter in a function call persists until the completion of the full-expression containing the call.

Our temporary (5) is bound to a reference parameter in a function call (to arg&& in convert()), so it persists until the end of the full-expression (which is the all of foo(convert(5)) ). So this is fine, as long as you don't let a reference to x escape foo().

Barry
  • 286,269
  • 29
  • 621
  • 977