Vector works properly
Header
std::vector<std::shared_ptr<SceneNode>> subnodes_m;
Definition
void CompositeSceneNode::AddChild(SceneNode* subnode_p)
{
subnodes_m.emplace_back(subnode_p);
}
Multimap doesn't
Header
std::multimap<unsigned int, std::shared_ptr<SceneNode>> subnodes_m;
Definition
void CompositeSceneNode::AddChild(SceneNode* subnode_p, unsigned int layerIndex)
{
subnodes_m.emplace(layerIndex, subnode_p);
}
I get following error:
error C2664: 'std::pair<_Ty1,_Ty2>::pair(const unsigned int &,const _Ty2 &)' :
cannot convert parameter 2 from 'RendererD3DWrapper::SceneNode *'
to 'const std::shared_ptr<_Ty> &'
Anybody has a clue?
You can't construct a std::pair<T1,T2> with arguments of types U and V if there is no implicit conversion of U into T1, and V into T2. In your case, there is no implicit conversion of SceneNode* into std::shared_ptr<SceneNode>.
From the C++ standard:
§ 20.3.2 Class template
pair[pairs.pair]template<class U, class V> constexpr pair(U&& x, V&& y);
Requires:
is_constructible<first_type, U&&>::valueistrueandis_constructible<second_type, V&&>::valueistrue.Effects: The constructor initializes
firstwithstd::forward<U>(x)andsecondwithstd::forward<V>(y).Remarks: If
Uis not implicitly convertible tofirst_typeorVis not implicitly convertible tosecond_typethis constructor shall not participate in overload resolution.
Having said that, you can't initialize a std::pair<T1,T2> like below (as emplace builds in-place a std::pair<key_type, mapped_type> known as value_type of std::multimap):
std::pair<unsigned int, std::shared_ptr<SceneNode>> p( 1, new SceneNode );
because the constructor of std::shared_ptr<T> taking a raw pointer (declared below) is an explicit constructor, hence the error you encounter:
§ 20.9.2.2 Class template
shared_ptr[util.smartptr.shared][...] template<class Y> explicit shared_ptr(Y* p);
In C++11 you should either build a std::shared_ptr<T> before calling emplace:
subnodes_m.emplace(layerIndex, std::shared_ptr<SceneNode>(subnode_p));
, or you can forward arguments to the constructors of pair's elements (rather than forwarding them to the constructor of std::pair<T1,T2> itself), with a piecewise construction:
subnodes_m.emplace(std::piecewise_construct
, std::forward_as_tuple(layerIndex)
, std::forward_as_tuple(subnode_p));
DEMO
Why does it work with
std::vectorofstd::shared_ptr's then?
The std::vector<std::shared_ptr<T>>::emplace_back member function forwards the arguments of emplace_back to the constructor of std::shared_ptr<T>, satisfying the explicit context requirement. In case of a map and a multimap, the emplaced type is a pair which has the constructor that forwards arguments further into its elements disabled if the conversion between argument's and parameter's types of those elements is not implicit (as cited above).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With