解決しました!下記参照
だから、私はいくつかの単純なデータ構造を実行し、それらをいじることによって C++11 を学ぼうとしています。生のポインターを使用して、次の BST の例と同様のことをnew
行いdelete
、正常に動作しました。それから、より漏れのない方法でそれをやりたかった.
// tree.cpp
//
//
#include <iostream>
#include <memory>
/* DECLARATIONS */
template <typename T>
struct Tree {
// members
T data;
std::unique_ptr<Tree<T> > left;
std::unique_ptr<Tree<T> > right;
// methods
Tree (T arg);
~Tree () = default;
void insert (Tree<T> child);
void insert (T arg);
void print (void);
};
template <typename T>
Tree<T>::Tree (T arg) {
data = arg;
left = nullptr;
right = nullptr;
}
template <typename T>
void Tree<T>::insert (Tree<T> child) {
if (child.data < data) {
if (left) {
left->insert(child);
} else {
left = &child;
}
} else {
if (right) {
right->insert(child);
} else {
right = &child;
}
}
}
template <typename T>
void Tree<T>::insert (T arg) {
Tree<T> child (arg);
this->insert(child);
}
template <typename T>
void Tree<T>::print (void) {
if (left) {
left->print();
}
std::cout << data;
if (right) {
right->print();
}
}
int main (void) {
Tree<int> root (0);
root.insert(3);
root.insert(-3);
root.insert(-2);
root.insert(2);
root.insert(11);
root.print();
return 0;
}
ただし、clang ++から得られるエラーは理解できません。
$ clang++ -std=c++11 tree.cpp
tree_new.cpp:50:16: error: call to deleted constructor of 'Tree<int>'
this->insert(child);
^~~~~
tree_new.cpp:66:8: note: in instantiation of member function 'Tree<int>::insert' requested here
root.insert(3);
^
tree_new.cpp:10:8: note: function has been explicitly marked deleted here
struct Tree {
^
tree_new.cpp:18:24: note: passing argument to parameter 'child' here
void insert (Tree<T> child);
^
tree_new.cpp:34:20: error: call to deleted constructor of 'Tree<int>'
left->insert(child);
^~~~~
tree_new.cpp:50:9: note: in instantiation of member function 'Tree<int>::insert'requested here
this->insert(child);
^
tree_new.cpp:66:8: note: in instantiation of member function 'Tree<int>::insert' requested here
root.insert(3);
^
tree_new.cpp:10:8: note: function has been explicitly marked deleted here
struct Tree {
^
tree_new.cpp:18:24: note: passing argument to parameter 'child' here
void insert (Tree<T> child);
^
2 errors generated.
を宣言したときにコンストラクターを明示的に削除したと表示されるのはなぜstruct
ですか? コンストラクターも明示的に定義しました。また、スコーピング/所有権の失敗に関するコメントをいただければ幸いです。とにかく、これは私がやったようにはうまくいかないだろうと確信しています。
解決
MSDNからの次のリンクは、 s の使用方法を明確にしunique_ptr
ました。
unique_ptr
問題の最初の説明 (暗黙的に a をメンバーとして使用すると (コンパイラーは「明示的に」と言いますが...)、クラスのコピー コンストラクターを削除します)、そして実際に Tree がまだ移動可能であることを指摘してくれた BatchyX に感謝します。
そのMSDNの記事で言及されていることstd::move()
は、その引数の右辺値を返すことです。
適切に変更されたコードを次に示します (明らかに変更された宣言を除く)。std::forward を使用することでまだいくつかの最適化が可能である可能性があることに注意してください。ただし、これは少なくとも正しくコンパイルおよび実行されるようです。
template <typename T>
void Tree<T>::insert (std::unique_ptr<Tree<T> >&& pchild) {
if (pchild->data < data) {
if (left) {
// recurse, but must match on the rvalue signature
left->insert(std::move(pchild));
} else {
// invokes the move constructor for left instead of its copy constructor
left = std::move(pchild);
}
} else {
if (right) {
right->insert(std::move(pchild));
} else {
right = std::move(pchild);
}
}
}
template <typename T>
void Tree<T>::insert (T arg) {
// what is inside the insert(...) is an rvalue.
this->insert(std::unique_ptr<Tree<T> >(new Tree<T> (arg)));
}