Note that there are some explanatory texts on larger screens.

plurals
  1. POC++11 Magically Deleted Constructor in BST
    text
    copied!<p><strong>SOLVED</strong>! See below</p> <p>So, I'm trying to learn C++11 by doing some simple data structures and playing around with them. I did something <em>similar</em> to the following BST example using raw pointers and <code>new</code> and <code>delete</code> and it worked fine. Then I wanted to do it in a way that was more leak-safe.</p> <pre><code>// tree.cpp // // #include &lt;iostream&gt; #include &lt;memory&gt; /* DECLARATIONS */ template &lt;typename T&gt; struct Tree { // members T data; std::unique_ptr&lt;Tree&lt;T&gt; &gt; left; std::unique_ptr&lt;Tree&lt;T&gt; &gt; right; // methods Tree (T arg); ~Tree () = default; void insert (Tree&lt;T&gt; child); void insert (T arg); void print (void); }; template &lt;typename T&gt; Tree&lt;T&gt;::Tree (T arg) { data = arg; left = nullptr; right = nullptr; } template &lt;typename T&gt; void Tree&lt;T&gt;::insert (Tree&lt;T&gt; child) { if (child.data &lt; data) { if (left) { left-&gt;insert(child); } else { left = &amp;child; } } else { if (right) { right-&gt;insert(child); } else { right = &amp;child; } } } template &lt;typename T&gt; void Tree&lt;T&gt;::insert (T arg) { Tree&lt;T&gt; child (arg); this-&gt;insert(child); } template &lt;typename T&gt; void Tree&lt;T&gt;::print (void) { if (left) { left-&gt;print(); } std::cout &lt;&lt; data; if (right) { right-&gt;print(); } } int main (void) { Tree&lt;int&gt; root (0); root.insert(3); root.insert(-3); root.insert(-2); root.insert(2); root.insert(11); root.print(); return 0; } </code></pre> <p>I don't undersatnd the error I'm getting from clang++, however.</p> <p><code>$ clang++ -std=c++11 tree.cpp</code></p> <pre><code>tree_new.cpp:50:16: error: call to deleted constructor of 'Tree&lt;int&gt;' this-&gt;insert(child); ^~~~~ tree_new.cpp:66:8: note: in instantiation of member function 'Tree&lt;int&gt;::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&lt;T&gt; child); ^ tree_new.cpp:34:20: error: call to deleted constructor of 'Tree&lt;int&gt;' left-&gt;insert(child); ^~~~~ tree_new.cpp:50:9: note: in instantiation of member function 'Tree&lt;int&gt;::insert'requested here this-&gt;insert(child); ^ tree_new.cpp:66:8: note: in instantiation of member function 'Tree&lt;int&gt;::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&lt;T&gt; child); ^ 2 errors generated. </code></pre> <p>Why does it say I explicitly deleted the constructor when I declared the <code>struct</code>? I even defined a constructor explicitly! Also, any comments on scoping/ownership failure would be appreciated. I'm pretty sure this won't work the way I did it anyways.</p> <p><strong>Solution</strong></p> <p>The following link from <a href="http://msdn.microsoft.com/en-us/library/vstudio/hh279676.aspx" rel="nofollow">MSDN</a> clarified how one can use <code>unique_ptr</code>s.</p> <p>Special thanks to BatchyX for his initial explanation of the problem (using a <code>unique_ptr</code> as a member implicitly (though the compiler says "explicitly"...) deletes the copy constructor for the class), and for noting that indeed Tree is still movable.</p> <p>Something mentioned in that MSDN article is that <code>std::move()</code> returns an rvalue of its argument.</p> <p>Here is the suitably modified code (excluding the obviously modified declarations). Note that there might be some optimizations possible still by using std::forward, but this at least seems to compile and run correctly.</p> <pre><code>template &lt;typename T&gt; void Tree&lt;T&gt;::insert (std::unique_ptr&lt;Tree&lt;T&gt; &gt;&amp;&amp; pchild) { if (pchild-&gt;data &lt; data) { if (left) { // recurse, but must match on the rvalue signature left-&gt;insert(std::move(pchild)); } else { // invokes the move constructor for left instead of its copy constructor left = std::move(pchild); } } else { if (right) { right-&gt;insert(std::move(pchild)); } else { right = std::move(pchild); } } } template &lt;typename T&gt; void Tree&lt;T&gt;::insert (T arg) { // what is inside the insert(...) is an rvalue. this-&gt;insert(std::unique_ptr&lt;Tree&lt;T&gt; &gt;(new Tree&lt;T&gt; (arg))); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload