Преобразование Lvalue в rvalue не выполняется

Следующая функция возвращает значение:

int foo()
{
int x = 42;
return x;    // x is converted to prvalue
}

Clang-х АСТ также показывает конверсию:

`-FunctionDecl <line:1:1, line:5:1> line:1:5 foo 'int ()'
`-CompoundStmt <line:2:1, line:5:1>
|-DeclStmt <line:3:5, col:15>
| `-VarDecl <col:5, col:13> col:9 used x 'int' cinit
|   `-IntegerLiteral <col:13> 'int' 42
`-ReturnStmt <line:4:5, col:12>
`-ImplicitCastExpr <col:12> 'int' <LValueToRValue>
^^^^^^^^^^^^^^
`-DeclRefExpr <col:12> 'int' lvalue Var 0x627a6e0 'x' 'int'

Далее также выполняется преобразование lvalue в rvalue, на этот раз для параметра, входящего в функцию.

void f(int i) {}
int main()
{
int x{3};
f(x);
}

АСТ включает преобразование:

`-FunctionDecl <line:2:1, line:6:1> line:2:5 main 'int ()'
`-CompoundStmt <line:3:1, line:6:1>
|-DeclStmt <line:4:5, col:13>
| `-VarDecl <col:5, col:12> col:9 used x 'int' listinit
|   `-InitListExpr <col:10, col:12> 'int'
|     `-IntegerLiteral <col:11> 'int' 3
`-CallExpr <line:5:5, col:8> 'void'
|-ImplicitCastExpr <col:5> 'void (*)(int)' <FunctionToPointerDecay>
| `-DeclRefExpr <col:5> 'void (int)' lvalue Function 0x6013660 'f' 'void (int)'
`-ImplicitCastExpr <col:7> 'int' <LValueToRValue>
^^^^^^^^^^^^^^
`-DeclRefExpr <col:7> 'int' lvalue Var 0x60138a0 'x' 'int'

Насколько я понимаю, аналогичным образом, следующее также должно требовать преобразования lvalue в rvalue.

struct A{};
void f(A a) {}
int main()
{
A a;
f(a);
}

Но это никогда не появляется в АСТ:

`-CallExpr <line:6:5, col:8> 'void'
|-ImplicitCastExpr <col:5> 'void (*)(A)' <FunctionToPointerDecay>
| `-DeclRefExpr <col:5> 'void (A)' lvalue Function 0x615e830 'f' 'void (A)'
`-CXXConstructExpr <col:7> 'A' 'void (const A &) noexcept'
`-ImplicitCastExpr <col:7> 'const A' lvalue <NoOp>
`-DeclRefExpr <col:7> 'A' lvalue Var 0x615ea68 'a' 'A'

Зачем? Является ли преобразование необязательным иногда?

2

Решение

Зачем? Является ли преобразование необязательным иногда?

Это не нужно, а подавлено.

Для типа класса A, f(a); вызывает конструктор копирования A быть призванным. Неявно определенный конструктор копирования принимает ссылку на lvalue (т.е. const A&), и преобразование lvalue в rvalue подавляется при привязке lvalue-reference.

[Dcl.init.ref] /5.1:

(5.1) Если ссылка является ссылкой lvalue …

[Примечание: обычные стандартные преобразования lvalue-to-rvalue, array-to-pointer и function-to-pointer не нужны и поэтому подавляются, когда такие прямые привязки к lvalue выполняются. — конец примечания]
2

Другие решения

AST показывает, что конструктор для A анализируется, а именно тот, который принимает значение lvalue const A& ( a в main) и конструирует a в f(A a), Здесь нет никакого значения.

`-CallExpr <line:6:5, col:8> 'void'
|-ImplicitCastExpr <col:5> 'void (*)(A)' <FunctionToPointerDecay>
| `-DeclRefExpr <col:5> 'void (A)' lvalue Function 0x615e830 'f' 'void (A)'
`-CXXConstructExpr <col:7> 'A' 'void (const A &) noexcept'
^^^^^^^^^^^^^^^^                    ^^^^^^^^^
`-ImplicitCastExpr <col:7> 'const A' lvalue <NoOp>
`-DeclRefExpr <col:7> 'A' lvalue Var 0x615ea68 'a' 'A'
1

По вопросам рекламы [email protected]