Cześć,
próbuję zrozumieć ideę idącą za value category i mam pewien problem.
Pierwszy przykład:
Otóż, jak na moje oko to ten kod powinien spowodować błąd podczas kompilacji (a co najmniej ostrzeżenie):
Link Wandbox: https://wandbox.org/permlink/OoIqDzPA9dy2LS3q
#include <iostream>
using namespace std;
void f(const int&& i) {
std::cout << &i;
}
int main() {
int a = 8;
f(7);
return 0;
}
Jednakże nic takiego się nie dzieje:
g++ prog.cc -Wall -Wextra -std=c++11 -pedantic
prog.cc: In function 'int main()':
prog.cc:11:6: warning: unused variable 'a' [-Wunused-variable]
int a = 8;
^
./a.out
0x7fffb87e2128
Jasne jest, że zmienna i
jest prvalue, jednak kompilator pozwala pobrać jej adres (co jest chyba niedozwolone), dlaczego? (nie pytam o to, że tworzy zmienną tymczasową i dlatego może).
Drugi przykład:
Link Wandbox: https://wandbox.org/permlink/Z3j3W0W1xBWcLfmO
struct S {
S& operator=(int) {
return *this;
}
};
int main() {
S() = 7;
return 0;
}
Kompilacja przebiega bez żadnych ostrzeżeń, dlaczego? Przecież po obu stronach wyrażenia S() = 7;
mamy prvalue.
Trzeci przykład:
Link Wandbox: https://wandbox.org/permlink/UWX0IrW51N2jeIR8
int main() {
int &i = int();
return 0;
}
Słusznie powoduje błąd kompilacji:
prog.cc:6:18: error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
int &i = int();
Jednakże drobna zmiana, powoduje że kompilator nie widzi problemu:
Link Wandbox: https://wandbox.org/permlink/4Nha8pJ9ThpOy5GO
int main() {
const int &i = int();
return 0;
}
A przecież jest to taka sama sytuacja - po prawej stronie prvalue, a po lewej lvalue przechowujące adres na prvalue.
Temporary materialization wchodzi w C++17, więc zakładam, że nie to jest powodem takiego zachowania. Czy są jakieś reguły, o których nie wiem?