How to implement perfect forwarding to a non-generic type?

Let's say I have the following code:

class Element;
typedef shared_ptr<Element> ElementPtr;

class Element
{
public:
    void add_child(const ElementPtr& elem);

private:
    vector<ElementPtr> children;
}

inline void Element::add_child(const ElementPtr& elem)
{
    children.push_back(elem);
};

And I want to update add_childto use excellent redirects. I tried to change the definition of the function (and declaration), so use the following logic:

void Element::add_child(ElementPtr&& elem)
{
    children.push_back(forward<ElementPtr>(elem));
}

But this is a failure for any call in which the argument elemis the value of l. So I thought that I would try with templates and come up with the following:

template <ElementPtr elem>
void Element::add_child(ElementPtr&& elem)
{
    children.push_back(forward<ElementPtr>(elem));
}

... But this does not compile. So I changed this to the following:

template <class T>
void Element::add_child(T&& elem)
{
    children.push_back(forward<T>(elem));
}

... which compiles and works, but seems ugly and wrong; add_childwill only accept type arguments ElementPtr, so shouldn't this declaration of this function reflect this?

, , ? , lvalue rvalue .

+1
1

  • ( " vector::push_back " ):

    void add_child(const ElementPtr& elem) { children.push_back(elem); }
    void add_child(ElementPtr&& elem) { children.push_back(std::move(elem)); }
    
  • , :

    void add_child(ElementPtr elem) { children.push_back(std::move(elem)); }
    
  • SFINAE.

    template <class T,
              class = std::enable_if_t<std::is_same<ElementPtr, std::decay_t<T>>{}>>
    void Element::add_child(T&& elem)
    {
        children.push_back(forward<T>(elem));
    }
    

2 , shared_ptr , . 1 , . 3 , .

+3

Source: https://habr.com/ru/post/1657233/


All Articles