2016-07-20 6 views
4

私はC++ 11のunique_ptrの使い方を簡単なリンクリストプログラムで学習しようとしています。私の人生のために、なぜ私はカスタム・デリゲーターを使うときにコンパイル・エラーが出るのか理解できません。C++ 11 unique_ptrをカスタムディテクタで使用

#include <cstdio> 
#include <limits> 
#include <memory> 
#include <cstdlib> 
#include <iostream> 

using namespace std; 

struct node { 
    int value; 
    struct node* next; 
}; 

typedef struct node Node; 

std::unique_ptr<Node> createList() 
{ 

    std::unique_ptr<Node> head(new Node); 
    Node* temp=head.get(); 
    temp->value=0; 
    for(int i=1;i<8;i++) { 
     if(temp->next==nullptr) { 
      temp->next=new Node(); 
      temp=temp->next; 
      temp->value=i; 
      temp->next=nullptr; 
     } 
    //temp=temp->next; 
    } 
    return head; 
} 

int main() 
{ 
    auto del1 = [](Node* p) { while(p) {std::cout << "Deleting value is : " << p->value;struct node* n=p->next;delete p; p=n;} return; }; 

    std::unique_ptr< Node, decltype(del1) > head(std::move(createList()),del1); 
} 

そして、ここでコンパイルエラーが

sh-4.3$ g++ -std=c++11 -o main *.cpp                             
main.cpp: In function 'int main()':                              
main.cpp:38:82: error: no matching function for call to 'std::unique_ptr<node, main()::<lambda(Node*)> >::unique_ptr(std::remove_reference<std::unique_ 
ptr<node> >::type, main()::<lambda(Node*)>&)'                           
     std::unique_ptr< Node, decltype(del1) > head(std::move(createList()),del1);                 
                       ^                 
In file included from /usr/include/c++/5.3.1/memory:81:0,                        
       from main.cpp:3:                              
/usr/include/c++/5.3.1/bits/unique_ptr.h:228:2: note: candidate: template<class _Up, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::auto_ptr<_Up>&&) 
    unique_ptr(auto_ptr<_Up>&& __u) noexcept;                            
^                                     
/usr/include/c++/5.3.1/bits/unique_ptr.h:228:2: note: template argument deduction/substitution failed:            
main.cpp:38:82: note: 'std::remove_reference<std::unique_ptr<node> >::type {aka std::unique_ptr<node>}' is not derived from 'std::auto_ptr<_Up>'  
     std::unique_ptr< Node, decltype(del1) > head(std::move(createList()),del1);                 
                       ^                 
In file included from /usr/include/c++/5.3.1/memory:81:0,                        
       from main.cpp:3:                              
/usr/include/c++/5.3.1/bits/unique_ptr.h:220:2: note: candidate: template<class _Up, class _Ep, class> std::unique_ptr<_Tp, _Dp>::unique_ptr(std::uniqu 
e_ptr<_Up, _Ep>&&)                                  
    unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept                          
^                                     
/usr/include/c++/5.3.1/bits/unique_ptr.h:220:2: note: template argument deduction/substitution failed:            
main.cpp:38:82: note: candidate expects 1 argument, 2 provided                      
     std::unique_ptr< Node, decltype(del1) > head(std::move(createList()),del1);  

ある任意のアイデア?

+1

移動していることでしょうか?私はすべてのアウトしようとしている – KABoissonneault

+0

をC++ 11で新しいものを使用すると、std :: moveはおそらく暗黙的に(createListがrvalueを返すので)必要ではありません。 – ashwinaj

+1

'createList'の戻り値の型はあなたのdeleterを含まないので、別の型です – Galik

答えて

4

あなたはcreateListから正しい型を返す必要があります。

#include <cstdio> 
#include <limits> 
#include <memory> 
#include <cstdlib> 
#include <iostream> 

using namespace std; 

struct node { 
    int value; 
    struct node* next; 
}; 

typedef struct node Node; 

auto createList() 
{ 
    auto del1 = [](Node* p) { while(p) {std::cout << "Deleting value is : " << p->value;struct node* n=p->next;delete p; p=n;} return; }; 
    std::unique_ptr< Node, decltype(del1) > head(new Node,del1); 

    Node* temp=head.get(); 
    temp->value=0; 
    for(int i=1;i<8;i++) { 
     if(temp->next==nullptr) { 
      temp->next=new Node(); 
      temp=temp->next; 
      temp->value=i; 
      temp->next=nullptr; 
     } 
    //temp=temp->next; 
    } 
    return head; 
} 

int main() 
{ 
    auto node = createList(); 
} 

をそれ以外の場合は、質問に示すコードでは、あなたは、異なるタイプのポインタである、内部データの所有権を取得し、それらを移動する必要があります

int main() 
{ 
    auto del1 = [](Node* p) { while(p) {std::cout << "Deleting value is : " << p->value;struct node* n=p->next;delete p; p=n;} return; }; 

    std::unique_ptr< Node, decltype(del1) > head(createList().release(),del1); 
} 

.release()への呼び出しに注意してください。
詳細については、hereを参照してください。

+0

ありがとう。私はあなたの2番目のオプションを試してみました。これは次のようになります。引数1の変換が 'std :: default_delete 'から 'const main():: __ lambda0&'に変更されていません。 – ashwinaj

+1

@ashwinaj [作品](https://godbolt.org/ g/5pa5h3)、何が問題なの? ? – skypjack

+0

Skypjack、元の質問にコンパイルエラーを追加しました。 – ashwinaj

1

unique_ptrの2つの引数のコンストラクタは、スマートポインタとデリゲータではなく、生ポインタとデリータを受け取ります。

例を安全にするために、createListはおそらく最初にすべてのノードを削除するunique_ptrを返すべきです。

+0

最も安全なのはおそらく 'Node'のデストラクタを正直にすることでしょう – KABoissonneault

2

createList()は、std::unique_ptr<Node>を返します。

unique_ptr(pointer p, /* see below */ d1); (3)  
unique_ptr(pointer p, /* see below */ d2); (4)  

そこでエラー:constructorあなたが使用しようとしているが、最初の引数としてNode*を取ります。

std::unique_ptr<Node, decltype(del1)> head(
    createList().release(), // NB release(), not get()! 
    del1); 

をかstd::unique_ptr<Node, decltype(del1)>を返すためにcreateList()自体を変更する:あなたはmain()にローカルなカスタムデリータを維持したい場合は

、あなただけのcreateListの外にポインタを引っ張っする必要があります。

+0

これは私が他の答えで言ったこととどう違うのでしょうか? – skypjack

+0

@skypjackこの回答を書いたときにリリースオプションがなく、OPのコードが機能しない理由についての説明がありません。 – Barry

+0

意味があります。私は 'release'への参照を編集で追加しましたが、あなたがその間に答えたことに気がつかなかった。ごめんなさい。 – skypjack

2

代替設計は、... `、なぜあなたは右辺値を`ヘッド(のstd ::移動(createList())では

struct Node { 
    Node(int value) : value(value) {} 

    int value; 
    std::unique_ptr<Node> next; 
}; 

std::unique_ptr<Node> createList() 
{ 
    std::unique_ptr<Node> head = std::make_unique<Node>(0); 

    Node* node = head.get(); 
    for(int i = 1; i < 8; i++) { 
     node->next = std::make_unique<Node>(i); 
     node = node->next.get(); 
    } 
    return head; 
} 
+0

@ashwinaj:もうカスタムデリターは必要ありません – Roland

関連する問題