Информация об изменениях

Сообщение Re[3]: Правомерно ли такое от 18.08.2020 11:20

Изменено 18.08.2020 11:30 rg45

Re[3]: Правомерно ли такое
Здравствуйте, Шахтер, Вы писали:

Ш>
Ш>template<typename ItemType>
Ш>inline
Ш>std::vector<ItemType>&& push_back_helper( std::vector<ItemType> &&v, const ItemType &elem )
Ш>{
Ш>    v.push_back(elem);
Ш>    return std::move(v);
Ш>}
Ш>


Ш>Но, вообще, это плохо. Коряво.

Ш>Лучше сделать что-то вроде

Я бы предложил еще один подход, основанный на максимально полном использовании perfect forwarding references. УПРОЩЕННЫЙ вариант, демонстрирующий идею, выглядит так:

template<typename ContainerT typename ItemT>
ContainerT push_back_helper(ContainerT&& v, ItemT&& item)
{
    v.push_back(std::forward<ItemT>(item));
    return std::forward<ContainerT>(v);
}


Для тех, пока еще не понял, в чем фокус объясняю: это функция-универсал — может возвращать как ссылку, так и значение — в зависимости от типа входного параметра. Когда входной параметр задается lvalue выражением, хоть константным, хоть неконстантным, функция возвращает ссылку — константную или неконстантную. Если же параметр задается rvalue выражением, функция вернет значение, применив при этом move. Преимущество такого подхода — одним выстрелом получается неплохой компромисс между эффективностью и надежностью. Код защищен от опасности возникновения висячих ссылок.

Ну а перегрузки и типовую безопасность придется достигать использованием SFINAE или концептов. И это слабая сторона такого подхода.
Re[3]: Правомерно ли такое
Здравствуйте, Шахтер, Вы писали:

Ш>
Ш>template<typename ItemType>
Ш>inline
Ш>std::vector<ItemType>&& push_back_helper( std::vector<ItemType> &&v, const ItemType &elem )
Ш>{
Ш>    v.push_back(elem);
Ш>    return std::move(v);
Ш>}
Ш>


Ш>Но, вообще, это плохо. Коряво.

Ш>Лучше сделать что-то вроде

Я бы предложил еще один подход, основанный на максимально полном использовании perfect forwarding references. УПРОЩЕННЫЙ вариант, демонстрирующий идею, выглядит так:

template<typename ContainerT typename ItemT>
ContainerT push_back_helper(ContainerT&& v, ItemT&& item)
{
    v.push_back(std::forward<ItemT>(item));
    return std::forward<ContainerT>(v);
}


Для тех, кто пока еще не понял, в чем фокус объясняю: это функция-универсал — может возвращать как ссылку, так и значение — в зависимости от типа входного параметра. Когда входной параметр задается lvalue выражением, хоть константным, хоть неконстантным, функция возвращает ссылку — константную или неконстантную. Если же параметр задается rvalue выражением, функция вернет значение, применив при этом move. Преимущество такого подхода — одним выстрелом получается неплохой компромисс между эффективностью и надежностью. Код защищен от опасности возникновения висячих ссылок.

Ну а перегрузки и типовую безопасность придется достигать использованием SFINAE или концептов. И это слабая сторона такого подхода.