3

I read a lot about it but still can't get. What's difference between these two variants:

template <typename val_t>
class fact_t: public exp_t<val_t> {
    val_t m_value;
public:
    fact_t(val_t &&value) : m_value{std::forward<val_t>(value)} {}
};

template <typename val_t>
class fact_t: public exp_t<val_t> {
    val_t m_value;
public:
    fact_t(val_t &&value) : m_value{std::move(value)} {}
};

Can someone show an example when one variant will fail but another will work still?

I tried to use the first variant the next way:

std::string str = "str";
fact_t<std::string> f(str);

But it leads to an error of compile time. Although as I understood from other topics and cppreference that str is lvalue and std::forward allows to use it. Where am I missing?

P.S. I'm sorry if is a stupid question but I really can't get.

Denis Sologub
  • 7,277
  • 11
  • 56
  • 123
  • 2
    Related: https://stackoverflow.com/questions/9671749/whats-the-difference-between-stdmove-and-stdforward. Also https://stackoverflow.com/a/16014527 – Kerrek SB Dec 13 '18 at 01:48
  • @KerrekSB I read this topic too – Denis Sologub Dec 13 '18 at 01:52
  • @KerrekSB, but when I tried to write a something like this `std::string x = "str"; fact_t f(x);`, it fails in both variants. Although as I understood it's **lvalue** and must work with `forward`. What is wrong? – Denis Sologub Dec 13 '18 at 01:54
  • @Jans I read this topic already. I've updated my question with more details. – Denis Sologub Dec 13 '18 at 02:01

1 Answers1

4

If val_t is not an lvalue reference type, then value in constructor is an rvalue reference, and std::forward is equivalent to std::move.

If val_t is an lvalue reference, then so is value. std::forward then returns an lvalue reference and the code compiles. std::move returns an rvalue reference, which cannot be bound to m_value (which is an lvalue reference), and compiler reports an error.

Demo

The reason fact_t<std::string> f(str); fails to compile is it's trying to pass an lvalue to a parameter that expects an rvalue.

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85