Рассмотрим следующий фрагмент кода:
struct S{
int i;
S(int);
S(const volatile S&);
};
struct S_bad{
int i;
};
volatile S as{0};
volatile S_bad as_bad{0};
volatile int ai{0};
void test(){
ai; //(1)=> a load is always performed
as; //(2)=> Should call the volatile copy constructor
as_bad; //(3)=> Should be ill-formed
}
Выражение ai;
, as;
и as_bad
- это отклоненные выражения значений и в соответствии со стандартным проектом С++ N4659/[expr].12 Я ожидал, что lvalue-to-rvalue применил бы в этих трех случаях. Для случая (2) это должно вызвать вызов конструктора летучих копий (S(const volatile S&)
) [expr]/12
[...] Если выражение является prvalue после этого необязательного преобразования, применяется временное преобразование материализации ([conv.rval]). [Примечание. Если выражение является значением lvalue типа класса, у него должен быть конструктор летучих копий для инициализации временного объекта, который является результирующим объектом преобразования lvalue-to-rvalue. - конечная нота]
Таким образом, случай (3) должен быть плохо сформирован.
Тем не менее, поведение компиляторов кажется хаотичным:
-
GCC:
-
ai;
= > загружает значениеai
; -
as;
= > не генерируется код, нет предупреждений; -
as_bad;
= > загружаетas_bad.i
.
-
-
Clang не создает нагрузку для случая (2) и генерирует предупреждение: результат выражения не используется; назначить в переменную для принудительной загрузки [-Wunused-volatile-lvalue]
-
ai;
= > загружает значениеai
; -
as;
= > не генерируется код; результат выражения предупреждения не используется; назначить в переменную для принудительной загрузки [-Wunused-volatile-lvalue] -
as_bad;
= > тот же, что иas;
.
-
-
MSVC выполняет загрузку в обоих случаях.
-
ai;
= > загружает значениеai
; -
as;
= > загружаетas.i
(без вызова конструктора летучих копий) -
as_bad;
= > загружаетas_bad.i
.
-
Резюме того, что я ожидал в соответствии со стандартом:
-
ai;
= > загружает значениеai
; -
as;
= > вызовS(const volatile S&)
сas
в качестве аргумента; -
as_bad;
= > генерировать ошибку компиляции
Является ли моя интерпретация стандарта правильной? Какой компилятор прав, если таковой имеется?