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
is true
and is_constructible<second_type, V&&>::value
is true
.
Effects: The constructor initializes first
with std::forward<U>(x)
and second
with std::forward<V>(y)
.
Remarks: If U
is not implicitly convertible to first_type
or V
is not implicitly convertible to second_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
of std::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).