Привязка 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и будет работать: вы получите свежийconstint локальная переменная i, содержащий копию значения в списке инициализатора. Вы можете сформировать неconst ссылки на эту локальную переменную.

Другие вопросы по тегам