Lab*_*ica 25 c++ overloading shared-ptr unique-ptr c++14
在我从前一个问题的答案中提示之后编写了一些东西,我遇到了重载Scene :: addObject的问题.
重申相关位并使其自包含,尽可能少的细节:
Interface,其中有FooS和BarS;Scene拥有这些物品的人;Foos应该是unique_ptrs和Bars将shared_ptr在我的主要(由于前一个问题中解释的原因);main它们传递到Scene实例,其取得所有权.最小的代码示例是这样的:
#include <memory>
#include <utility>
class Interface
{
public:
virtual ~Interface() = 0;
};
inline Interface::~Interface() {}
class Foo : public Interface
{
};
class Bar : public Interface
{
};
class Scene
{
public:
void addObject(std::unique_ptr<Interface> obj);
// void addObject(std::shared_ptr<Interface> obj);
};
void Scene::addObject(std::unique_ptr<Interface> obj)
{
}
//void Scene::addObject(std::shared_ptr<Interface> obj)
//{
//}
int main(int argc, char** argv)
{
auto scn = std::make_unique<Scene>();
auto foo = std::make_unique<Foo>();
scn->addObject(std::move(foo));
// auto bar = std::make_shared<Bar>();
// scn->addObject(bar);
}
Run Code Online (Sandbox Code Playgroud)
取消注释注释行会导致:
error: call of overloaded 'addObject(std::remove_reference<std::unique_ptr<Foo, std::default_delete<Foo> >&>::type)' is ambiguous
scn->addObject(std::move(foo));
^
main.cpp:27:6: note: candidate: 'void Scene::addObject(std::unique_ptr<Interface>)'
void Scene::addObject(std::unique_ptr<Interface> obj)
^~~~~
main.cpp:31:6: note: candidate: 'void Scene::addObject(std::shared_ptr<Interface>)'
void Scene::addObject(std::shared_ptr<Interface> obj)
^~~~~
Run Code Online (Sandbox Code Playgroud)
取消注释共享和注释的独特的东西也编译,所以我认为问题是,如编译器所说,在重载.但是我需要重载,因为这两种类型都需要存储在某种集合中,并且它们确实被保存为指向base的指针(可能全部移入shared_ptrs).
我正在传递两个值,因为我想说清楚我正在取得所有权Scene(并为shared_ptrs 增加参考计数器).对我来说不是很清楚问题在哪里,我在其他地方找不到任何这样的例子.
Cal*_*eth 18
你遇到的问题是shared_ptr(13)的这个构造函数(它不是显式的),与unique_ptr(6)的类似"移动派生到基础"构造函数(也不是显式)一样好.
template< class Y, class Deleter >
shared_ptr( std::unique_ptr<Y,Deleter>&& r ); // (13)
Run Code Online (Sandbox Code Playgroud)
13)构造一个
shared_ptr管理当前管理的对象的r.r存储与之关联的删除器以供将来删除受管对象.r通话后不管理任何对象.如果
std::unique_ptr<Y, Deleter>::pointer不兼容,则此重载不参与重载解析T*.如果r.get()是空指针,则此重载等效于默认构造函数(1).(自C++ 17起)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept; //(6)
Run Code Online (Sandbox Code Playgroud)
6)
unique_ptr通过转移所有权u来构造a*this,其中u使用指定的删除符(E)构造.如果满足以下所有条件,则此构造函数仅参与重载解析:
a)
unique_ptr<U, E>::pointer可隐式转换为指针b)
U不是数组类型c)要么
Deleter是引用类型,要么是E类型D,要么Deleter不是引用类型,并且E可以隐式转换为D
在非多态的情况下,您正在构造一个unique_ptr<T>from unique_ptr<T>&&,它使用非模板移动构造函数.重载决策更喜欢非模板
我打算假设Scene商店shared_ptr<Interface>.在这种情况下,你不需要超载addObject的unique_ptr,你可以只允许在呼叫中的隐式转换.
另一个答案解释了歧义和可能的解决方案。这是另一种方法,以防您最终需要两个重载;在这种情况下,您始终可以添加另一个参数以消除歧义并使用标签调度。样板代码隐藏在以下的私有部分Scene:
class Scene
{
struct unique_tag {};
struct shared_tag {};
template<typename T> struct tag_trait;
// Partial specializations are allowed in class scope!
template<typename T, typename D> struct tag_trait<std::unique_ptr<T,D>> { using tag = unique_tag; };
template<typename T> struct tag_trait<std::shared_ptr<T>> { using tag = shared_tag; };
void addObject_internal(std::unique_ptr<Interface> obj, unique_tag);
void addObject_internal(std::shared_ptr<Interface> obj, shared_tag);
public:
template<typename T>
void addObject(T&& obj)
{
addObject_internal(std::forward<T>(obj),
typename tag_trait<std::remove_reference_t<T>>::tag{});
}
};
Run Code Online (Sandbox Code Playgroud)
完整的可编译示例在这里。
| 归档时间: |
|
| 查看次数: |
1305 次 |
| 最近记录: |