放置指向shared_ptr的多重映射的指针不起作用

Emplace a pointer to a multimap of shared_ptr's doesn't work

本文关键字:指针 不起作用 映射 ptr shared      更新时间:2023-10-16

Vector 工作正常

Header
std::vector<std::shared_ptr<SceneNode>> subnodes_m;
Definition
void CompositeSceneNode::AddChild(SceneNode* subnode_p)
{
    subnodes_m.emplace_back(subnode_p);
}

多重地图没有

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);
}

我收到以下错误:

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> &'   

有人有头绪吗?

如果没有将

U隐式转换为T1,并且V转换为T2,则无法使用类型为UV的参数构造std::pair<T1,T2>。在您的情况下,没有将SceneNode*隐式转换为std::shared_ptr<SceneNode>

从C++标准:

§ 20.3.2 类模板pair [pairs.pair]

template<class U, class V> constexpr pair(U&& x, V&& y);
  1. 要求:is_constructible<first_type, U&&>::value trueis_constructible<second_type, V&&>::value true

  2. 效果:构造函数用std::forward<U>(x)初始化first,用std::forward<V>(y)初始化second

  3. 备注:如果U不能隐式转换为first_typeV不能隐式转换为second_type则此构造函数不应参与重载解析

话虽如此,您不能像下面这样初始化std::pair<T1,T2>(因为emplace构建了一个称为std::multimap value_type std::pair<key_type, mapped_type>(:

std::pair<unsigned int, std::shared_ptr<SceneNode>> p( 1, new SceneNode );

因为std::shared_ptr<T>获取原始指针(下面声明(的构造函数是explicit构造函数,因此您遇到的错误:

§ 20.9.2.2 类模板shared_ptr [util.smartptr.shared]

[...]
template<class Y> explicit shared_ptr(Y* p);

在 C++11 中,您应该在调用 emplace 之前构建一个std::shared_ptr<T>

subnodes_m.emplace(layerIndex, std::shared_ptr<SceneNode>(subnode_p));

或者您可以使用分段构造将参数转发给 pair 元素的构造函数(而不是将它们转发给 std::pair<T1,T2> 本身的构造函数(:

subnodes_m.emplace(std::piecewise_construct
                 , std::forward_as_tuple(layerIndex)
                 , std::forward_as_tuple(subnode_p));

演示

那么为什么它适用于std::shared_ptrstd::vector呢?

std::vector<std::shared_ptr<T>>::emplace_back成员函数将emplace_back的参数转发给std::shared_ptr<T>的构造函数,满足显式上下文要求。在mapmultimap的情况下,放置类型是一个pair,如果参数和参数的元素类型之间的转换不是隐式的(如上所述(,则禁用将参数进一步转发到其元素中的构造函数。