While implementing a BS Tree, I noticed some things that I wasn't so sure about since I started using C++11 smart pointers and it makes me wonder why it is so. The code below works fine if I use init-brace pairs{} instead of the parentheses; my personal rule is to value initialize every member(directly or through a ctor) and since Node::right and Node::left are both smart pointers, therefore, nullptr it is. Question 1 : Why does the parentheses fail and init-brace pairs succeed? In this case ONLY, is there any semantic difference between the two?
In BST , in the ctor that takes an std::initializer_list, I understand that std::initializer_list elements are only copyable, according to this . So if I'm not wrong, according to Scott Meyer at the recent GN13, performing a move on a const object would only trigger the copy-ctor of the object.
Quesion 2 Why does the compiler fail to copy the object at the call to BST::insert( T&& ) ?
#include <memory>
template<typename T>
struct Node
{
//~ std::unique_ptr<Node<T>> left ( nullptr ), right ( nullptr );
std::unique_ptr<Node<T>> left { nullptr }, right { nullptr };
Node<T> *parent = nullptr;
T value { };
Node<T> () = default;
Node<T> ( T && val, Node<T> * _left = nullptr, Node<T> *_right = nullptr,
Node<T> *_parent = nullptr ): left( _left ), right ( _right ), parent( _parent ),
value ( std::move( val ) )
{
}
};
template<typename T>
struct BinarySearchTree
{
std::unique_ptr<Node<T>> root;
BinarySearchTree(): root { nullptr } { }
BinarySearchTree( std::initializer_list<T> && lst ): BinarySearchTree { }{
//If the below code were changed to
//~ for( auto && i: lst ){ it would be an error
for( typename std::remove_reference<typename std::remove_const<T>::type>::type i: lst ){
this->insert( std::move( i ) );
}
}
void insert( T && v ) { }
};
int main(){
BinarySearchTree<int> a { 11, 24 };
return 0;
}
Why does the parentheses fail and init-brace pairs succeed?
Because parentheses are used for function declarations. You cannot use them to initialise variables at class scope. Even int i(1);
won't work.
Why does the compiler fail to copy the object at the call to BST::insert( T&& ) ?
You're not being fair in your comparison. In your auto
version, you explicitly ask for a reference type. In your non- auto
version, you explicitly ask for a non-reference type. Removing the &&
would make the auto
version work too.
Your insert
method takes a T &&
. That's a non- const
-qualified reference, so it cannot bind to any const
object.
auto &&
is deduced to const int &&
, because you cannot change the contents of an initializer_list<int>
: its begin()
and end()
methods return const int *
. Adding std::move
doesn't work, you cannot bypass const
like that.
auto
would deduce to int
, and would work: you'd get a fresh non- const
int
local variable i
, containing a copy of the value in the initialiser list. You can form non- const
references to that local variable.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.