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

Сообщение Re[6]: MSVC: A non-const reference may only be bound to an l от 26.07.2023 14:03

Изменено 26.07.2023 14:06 Sm0ke

Re[6]: MSVC: A non-const reference may only be bound to an l
Здравствуйте, so5team, Вы писали:

S>Это да. Но поинт в том, что пока std::max работает, у вас валидная ссылка. Иначе бы вот такой вот пример не работал бы:

S>
S>#include <string>
S>#include <iostream>

S>using namespace std::string_literals;

S>int main()
S>{
S>    auto v = std::max(std::max(std::max("One"s, "Two"s), "Three"s), "Zero"s);
S>    std::cout << v << std::endl;
S>}
S>

S>Но он работает.

S>Потому что в выражении, где std::max вызываются, ссылки валидные. Но когда выражение завершается, уничтожаются все временные объекты, созданные в процессе его выполнения, поэтому ссылка и протухает.


S>Именно из-за этого ссылку нельзя сохранять. Но вот передать ее в конструктор объекта (как в примере) можно, т.к. она все еще валидная.


Понял, спасибо.

Но вот в чём могут быть подводные камни с предложением сделать так из исходной задачи

typedef std::set<unsigned>  UnsignedSet;

inline
UnsignedSet&& operator<<(UnsignedSet &&us, unsigned u)
{
    us.insert(u);
    return std::move(us);
}


Результат оператора << в таком виде нельзя напрямую передать в range for

for(
  unsigned it : (UnsignedSet{} << 2u << 10u)
) {}


И придётся писать более длинно, чтобы ссылка не провисла

for(
  UnsignedSet res = (UnsignedSet{} << 2u << 10u) // не rvalue
  unsigned it : res
) {}
Re[6]: MSVC: A non-const reference may only be bound to an l
Здравствуйте, so5team, Вы писали:

S>Это да. Но поинт в том, что пока std::max работает, у вас валидная ссылка. Иначе бы вот такой вот пример не работал бы:

S>
S>#include <string>
S>#include <iostream>

S>using namespace std::string_literals;

S>int main()
S>{
S>    auto v = std::max(std::max(std::max("One"s, "Two"s), "Three"s), "Zero"s);
S>    std::cout << v << std::endl;
S>}
S>

S>Но он работает.

S>Потому что в выражении, где std::max вызываются, ссылки валидные. Но когда выражение завершается, уничтожаются все временные объекты, созданные в процессе его выполнения, поэтому ссылка и протухает.


S>Именно из-за этого ссылку нельзя сохранять. Но вот передать ее в конструктор объекта (как в примере) можно, т.к. она все еще валидная.


Понял, спасибо.

Но вот в чём могут быть подводные камни с предложением сделать так из исходной задачи

typedef std::set<unsigned>  UnsignedSet;

inline
UnsignedSet&& operator<<(UnsignedSet &&us, unsigned u)
{
    us.insert(u);
    return std::move(us);
}


Результат оператора << в таком виде нельзя напрямую передать в range for

for(
  unsigned it : (UnsignedSet{} << 2u << 10u)
) {}


И придётся писать более длинно, чтобы ссылка не провисла

for(
  UnsignedSet res = (UnsignedSet{} << 2u << 10u) // не rvalue, а move constructor
  unsigned it : res
) {}


В случае с UnsignedSet operator<< использовать проще, не опасаясь не правильно использовать либу.