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_child
to use perfect forwarding. I tried changing the function definition (and declaration) so use the following logic:
void Element::add_child(ElementPtr&& elem)
{
children.push_back(forward<ElementPtr>(elem));
}
But this crashes for any call in which the argument elem
is an lvalue. So I thought I'd try it with templates and came 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 it to this:
template <class T>
void Element::add_child(T&& elem)
{
children.push_back(forward<T>(elem));
}
...Which compiles and works, but seems ugly and improper; add_child
will only ever accept arguments of type ElementPtr
, so shouldn't its function declaration reflect this?
Is there any way to implement perfect forwarding for a function while syntactically demonstrating that it only accepts one kind of variable? I basically want a function that will automatically distinguish between lvalue and rvalue versions of a specific parameter type.