2017-06-28 5 views
2

スマートポインタのクラスがあります:テスト用スマートポインタを関数に渡すには?

template <typename T> 
class UniquePtr { 
public: 
    UniquePtr(T* obj) 
     : obj(obj) 
    { 
    } 
    UniquePtr(const UniquePtr& ptr) = delete; 
    UniquePtr(UniquePtr&& ptr) 
    { 
     std::cout << "!! use of move !!" << std::endl; 
     obj = std::move(ptr.obj); 
     ptr.obj = nullptr; 
    } 

    UniquePtr& operator=(const UniquePtr& ptr) = delete; 
    UniquePtr& operator=(const UniquePtr&& ptr) = delete; 

    ~UniquePtr() 
    { 
     delete obj; 
    } 

private: 
    T* obj; 
}; 

クラス:

class Test { 
public: 
    Test() 
    { 
     std::cout << "Test is created" << std::endl; 
    } 
    Test(const Test& obj) = delete; 
    Test(const Test&& obj) = delete; 
    Test& operator=(const Test& obj) = delete; 
    Test& operator=(const Test&& obj) = delete; 
    virtual ~Test() 
    { 
     std::cout << "Test is destructed" << std::endl; 
    } 
}; 

と機能:

void function(UniquePtr<Test>&& ptr) 
{ 
    std::vector<UniquePtr<Test>> v; 
    v.push_back(std::move(ptr)); 
} 

私がテストクラスを渡すと、すべてがOKです:

UniquePtr<Test> ptr(new Test); 
function(std::move(ptr)); 

しかし、私はテストクラスから派生渡した場合、コードがコンパイルされていません。

class TestChild : public Test { 
public: 
    TestChild() 
    { 
     std::cout << "Test child is created" << std::endl; 
    } 
    TestChild(const TestChild& obj) = delete; 
    TestChild(const TestChild&& obj) = delete; 
    TestChild& operator=(const TestChild& obj) = delete; 
    TestChild& operator=(const TestChild&& obj) = delete; 
    virtual ~TestChild() 
    { 
     std::cout << "Test child is destructed" << std::endl; 
    } 
}; 
UniquePtr<TestChild> ptr(new TestChild); 
function(std::move(ptr)); 
error: invalid initialization of reference of type ‘UniquePtr&&’ from 
expression of type ‘std::remove_reference&>::type {aka UniquePtr}’ 
function(std::move(ptr)); ~~~~~~~~~^~~~~ 

は、どのように私はこのコードの作品std::unique_ptrUniquePtr<Test>&&UniquePtr<TestChild>を転換することができます。どのようにstd::unique_ptr handles itのような多くの

+4

(フル答えのための時間を持っていない)[ 'のstd :: unique_ptr'](http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr)は、そのコンストラクタを提供します変換を可能にします: 'template unique_ptr(unique_ptr && u)noexcept;'この機能を複製する必要があります – AndyG

+0

これは奇妙です: 'obj = std :: move(ptr.obj);' objはポインタである。 – YSC

+0

@YSC、はい、そうです、それは必要ではありません:) – devalone

答えて

2

、あなたは、あなたのUniquePtrの状態を初期化するために使用されます(SFINAEが継承チェックに対処できるように)異なるタイプのUniquePtrを取り、あなたのクラスのテンプレートコンストラクタを提供する必要があります。

template<typename U> 
UniquePtr(UniquePtr<U> && other) { 
    obj = other.obj;//Won't compile if U is not a subclass of T. 
    other.obj = nullptr; 
} 
+0

ありがとう、それは動作します。しかし、私はこのようなコンストラクタを作成します: ' テンプレート UniquePtr(UniquePtr && ptr) { obj = ptr.get(); ptr.reset(); } ' ' Unique_Ptr 'は他の型を持ち、objにアクセスできないので – devalone

+0

愚かなマークダウン – devalone

+1

@devaloneそれはうまくいくはずです。 – Xirema