Do I use std::forward or std::move here?

后端 未结 3 1832
花落未央
花落未央 2021-02-06 01:41

Let\'s say I have:

template
struct NodeBase
{
    T value;
    NodeBase(T &&value)
        : value(value) { }
};

and I i

3条回答
  •  遥遥无期
    2021-02-06 02:11

    Probably neither.

    What I suspect you should have is:

    template
    struct NodeBase
    {
      T value;
      NodeBase(NodeBase &&) = default;
      NodeBase(NodeBase const&) = default; // issue: this might not work with a `T&`, but we can conditionally exclude it through some more fancy footwork
      NodeBase(NodeBase &) = default;
      template::value >::type >
      NodeBase(U &&u)
        : value(std::forward(u)) { }
    };
    
    template
    struct Node : public NodeBase
    {
      Node( Node & ) = default;
      Node( Node const& ) = default; // issue: this might not work with a `T&`, but we can conditionally exclude it through some more fancy footwork
      Node( Node && ) = default;
      template>::value >::type>
      Node(U && u)
        : NodeBase( std::forward(u) ) { }
    };
    

    unless you are doing something exceedingly strange.

    By exceedingly strange, it means that if your T is an int, you want to only accept moved-from values into your Node, but if your T is an int&, you accept only non-const lvalue ints, and if T is an int const&, you accept any value convertible to int.

    This would be a strange set of requirements to place on the constructor of NodeBase. I can think of situations where this might be the case, but they are not common.

    Assuming you simply want NodeBase to store that data, taking T&& in the constructor is not the right thing to do -- if you are storing an int in NodeBase, you probably are willing to make copies of that int, instead of only accepting moved-from ints.

    The above code does exactly that -- it allows anything that could be stored in the NodeBase to be passed on up to said NodeBase, with perfect forwarding.

    On the other hand, if you actually want the strange set of construction restrictions, then this is not the right answer for you. I've used that when I was building the a template type that was built from a universal reference argument, and I did want to restrict the passed in type to match the universal reference argument exactly, and store it iff the argument was an rvalue reference, and otherwise keep a reference to it.

提交回复
热议问题