При реализации BS Tree я заметил некоторые вещи, в которых я не был так уверен, так как начал использовать умные указатели C ++ 11, и это заставляет меня задуматься, почему это так. Код ниже работает нормально, если я использую пары init-brace {} вместо скобок; мой личный правило это значение инициализировать каждого члена (напрямую или через ctor) и с Узел :: право а также Узел :: влево оба умные указатели, следовательно, nullptr это.
Вопрос 1: Почему скобки терпят неудачу и пары init-brace успешны? В этом случае ТОЛЬКО есть ли смысловая разница между этими двумя понятиями?
В BST, в ctor, который принимает std :: initializer_list, я понимаю, что элементы std :: initializer_list могут копироваться только в соответствии с этот. Так что, если я не ошибаюсь, согласно Скотту Мейеру на недавнем GN13, выполнение перемещения объекта const вызовет только копирование-ctor объекта.
Вопрос 2 Почему компилятор не может скопировать объект при вызове 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;
}
Почему скобки терпят неудачу и пары init-brace успешны?
Потому что круглые скобки используются для объявлений функций. Вы не можете использовать их для инициализации переменных в области видимости класса. Четное int i(1);
не сработает
Почему компилятор не может скопировать объект при вызове BST :: insert (T&& )
Вы не честны в сравнении. В вашем auto
версия, вы явно запрашиваете ссылочный тип. В вашем неauto
версия, вы явно запрашиваете не ссылочный тип. Удаление &&
сделает auto
версия тоже работает.
Ваш insert
метод занимает T &&
, Это неconst
квалифицированная ссылка, поэтому она не может const
объект.
auto &&
выводится const int &&
потому что вы не можете изменить содержимое initializer_list<int>
: его begin()
а также end()
методы возврата const int *
, Добавление std::move
не работает, вы не можете обойти const
как это.
auto
выведет int
и будет работать: вы получите свежийconst
int
локальная переменная i
, содержащий копию значения в списке инициализатора. Вы можете сформировать неconst
ссылки на эту локальную переменную.