Мало того, что такой функции нет, никогда не может быть .Это может привести к тому, что четко определенные программы будут плохо сформированы или будут иметь худшее значение с неопределенным поведением.
Рассмотрим эту простую правильно сформированную программу:
struct X {};
auto bar(X x) -> decltype(x)
{
return x;
}
auto test()
{
bar(X{});
}
Как бы вы ее преобразовали?Невозможно заставить bar
взять ссылку и не изменять семантику программы или сделать ее UB
Если вы сделаете bar
ссылку на l-значение, тогда она не сможет принять временную:
struct X {};
auto bar(X& x) -> decltype(x)
{
return x;
}
auto test()
{
bar(X{});
}
<source>:12:5: error: no matching function for call to 'bar'
bar(X{});
^~~
<source>:4:6: note: candidate function not viable: expects an l-value for 1st argument
auto bar(X& x) -> decltype(x)
^
1 error generated.
Если вы возьмете ссылку на r-значение, вы не сможете вернуть ее без дальнейших изменений:
struct X {};
auto bar(X&& x) -> decltype(x)
{
return x;
}
auto test()
{
bar(X{});
}
<source>:6:12: error: rvalue reference to type 'X' cannot bind to lvalue of type 'X'
return x;
^
1 error generated.
Хорошо, вы можете решить эту конкретную проблему, переместив параметр.Но это намного выше того, что вы изначально хотели изменить.Тем не менее, ради аргумента, скажем, вы делаете, или что оригинальная программа уже делала это:
#include <utility>
struct X { };
auto bar(X&& x) -> decltype(x)
{
return std::move(x);
}
auto test()
{
bar(X{});
}
Это, наконец, действительно компилируется.Но вы видите проблему?Вы возвращаете ссылку на просроченный объект, вы возвращаете висячую ссылку:
// before
#include <utility>
struct X { auto foo() const {} };
auto bar(X x) -> decltype(x) // bar returns a prvalue
{
return x;
// or
// return std::move(x); // redundant, but valid and equivalent
}
auto test()
{
const X& xr = bar(X{}); // xr prolongs the lifetime of the temporary returned by `bar`
xr.foo(); // OK, no problem
}
// after
#include <utility>
struct X { auto foo() const {} };
auto bar(X&& x) -> decltype(x) // now bar returns an xvalue
{
return std::move(x);
}
auto test()
{
const X& xr = bar(X{}); // xr cannot prolong the life of an xvalue
// the temporary objects created as part of calling `bar` is now expired
// and xr references it
// any attempt to use xr results in UB
xr.foo(); // Undefined Behaviour
}
Невозможно сделать то, что вы хотите сделать.
Бремя лежит на васПрограммист: если вам нужны значения, пишите значения, если вам нужны ссылки, пишите ссылки.Это так просто.