Рассмотрим следующий фрагмент кода:
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;= > генерировать ошибку компиляции
Является ли моя интерпретация стандарта правильной? Какой компилятор прав, если таковой имеется?