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&&>::value
istrue
andis_constructible<second_type, V&&>::value
istrue
.Effects: The constructor initializes
first
withstd::forward<U>(x)
andsecond
withstd::forward<V>(y)
.Remarks: If
U
is not implicitly convertible tofirst_type
orV
is not implicitly convertible tosecond_type
this 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::vector
ofstd::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