1
  1. Is there any difference between int&& i = 42; and int i = 42; ?

  2. Regarding std::forward, I read online that "if arg is an lvalue reference, the function returns arg without modifying its type." However the following code:

void f(int& k)
{
    std::cout << "f(int&) " << k << std::endl;
}

void f(int&& k)
{
    std::cout << "f(int&&) " << k << std::endl;
}

int main(void)
{
    int i = 42;
    int& j = i;
    int&& k = 42;

    f(i);
    f(j);
    f(k);

    f(std::forward<int>(i));
    f(std::forward<int>(j));
    f(std::forward<int>(k));
    return 0;
}

prints out

f(int&) 42
f(int&) 42
f(int&) 42
f(int&&) 42
f(int&&) 42
f(int&&) 42

I'm wondering why the 4th and 5th lines aren't f(int&) 42, as per the quote I mentioned above.

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
Pippin
  • 323
  • 1
  • 9
  • 1
    `std::forward` is meant to be used with template argument that was deduced. – LogicStuff Jul 22 '16 at 10:49
  • Does this mean that I should never call `std::forward` inside a function that is neither a template function nor a template class member function? – Pippin Jul 22 '16 at 10:53
  • Because you use `std::forward`, making it return `int &&`. Try `std::forward` and you'll get `f(int&)`. Basically, it's `static_cast`, with `T` being `int` in your case. I'm not implying such usage of `std::forward` makes sense, by the way. – lapk Jul 22 '16 at 10:59
  • 1
    It's all [here](http://en.cppreference.com/w/cpp/utility/forward). Using `std::forward` does not make sense because it's the very template parameter that says whether `std::forward` will return rvalue or lvalue. In this case `std::forward(i)` is equivalent to `std::move(i)` and `std::forward(i)` is equivalent to `i`. – LogicStuff Jul 22 '16 at 10:59
  • @Pippin : Related link http://stackoverflow.com/questions/35314093/passing-int-to-fint/35314267 – msc Jul 22 '16 at 11:01
  • Your quote appears to come from http://www.cplusplus.com/reference/utility/forward/. cplusplus.com is not a good reference. Please consider using alternatives, for instance cppreference.com already linked in a comment and answer. –  Jul 22 '16 at 11:23

2 Answers2

1
  1. Is there any difference between int&& i = 42; and int i = 42; ?

Yes. Former variable is an rvalue reference to int which is bound to a temporary int object. Latter variable is an int object. The former is an unnecessarily convoluted way to refer to an object.

No, there is no difference in the context of 2. part of your question.

  1. ... "if arg is an lvalue reference, the function returns arg without modifying its type." ...

The quote isn't exactly accurate by itself. It makes an assumption, that the template argument of forward was deduced from the type of arg. You didn't use a deduced type, but instead int which would not have been deduced from an lvalue reference.

I'm wondering why the 4th and 5th lines aren't f(int&) 42

int is not an lvalue reference, so the quote does not apply to 4th line.

Let us consider, what exatly does std::forward do? It does this:

Returns: static_cast<T&&>(t).

Now, if T is int, then it does static_cast<int&&>(t), so the result type is an rvalue reference, regardless of the type of t. If you use a non-lvalue-reference as the type argument to std::forward, it behaves exactly like a std::move.

To comply with the assumptions of the quote, you could have done:

f(std::forward<decltype(i)>(i));
f(std::forward<decltype(j)>(j));
f(std::forward<decltype(k)>(k));

With this, the output is:

f(int&&) 42
f(int&) 42
f(int&&) 42
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • I'm still somewhat confused. Would you mind showing a code where `i` and `k` produce different results? – Pippin Jul 22 '16 at 10:59
  • @Pippin I didn't say they produce different results. I answered the question `Is there any difference between`. There can be a difference between things, even if they behave the same in some regard. – eerorika Jul 22 '16 at 11:01
  • @Pippin the only code giving different results in 1. is `decltype(i)` – M.M Jul 22 '16 at 11:04
0

I would say the function is pretty well explained here. When in a context where you can have universal references (T&& where T is deduced for that context), forward ensures that you relay the arguments with the same characteristics of l/r-valueness.

Javier Martín
  • 2,537
  • 10
  • 15