Привязка const rvalue к ссылке rvalue
При реализации BS Tree я заметил некоторые вещи, в которых я не был так уверен, так как начал использовать умные указатели C++11, и это заставляет меня задуматься, почему это так. Код ниже работает нормально, если я использую пары init-brace {} вместо скобок; Мое личное правило состоит в том, чтобы инициализировать значение каждого члена (напрямую или через ctor), и поскольку Node::right и Node::left оба являются умными указателями, следовательно, 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;
}
1 ответ
Почему скобки терпят неудачу и пары 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
ссылки на эту локальную переменную.