Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Применяется ли временное преобразование материализации к операнду const_cast

Автор вопроса: xmh0511Ответов: 1
int main(){
  const_cast<int&&>(0);
}

Согласно expr.const.cast № 4

Для двух типов объектов T1 и T2, если указатель на T1 может быть явно преобразован в тип "указатель на T2" с помощью const_cast, тогда также могут быть выполнены следующие преобразования:

  • lvalue типа T1 может быть явно преобразовано в lvalue типа T2, используя приведение const_cast ‹T2 &›;
  • glvalue типа T1 может быть явно преобразован в xvalue типа T2, используя приведение const_cast ‹T2 &&›; а также
  • если T1 является типом класса, prvalue типа T1 может быть явно преобразовано в xvalue типа T2, используя приведение const_cast ‹T2 &&›.

Результат ссылки const_cast относится к исходному объекту, если операнд является значением glvalue, и к результату применения преобразования временной материализации в противном случае.

Поскольку операнд 0 - это prvalue типа int, а указанный тип - это ссылка rvalue типа int. Следовательно, второй пункт может быть применен здесь после выполнения временного преобразования материализации, при котором операндом источника будет значение gl согласно expr # basic.lval-7

Каждый раз, когда prvalue появляется как операнд оператора, который ожидает glvalue для этого операнда, применяется временное преобразование материализации для преобразования выражения в xvalue.

Однако этот фрагмент отклонен как Clang, так и GCC. Если мы изменим операнд на int{0}

int main(){
  const_cast<int&&>(int{0});
}

Код принимает только GCC. Но следующий код по-прежнему не может быть скомпилирован GCC.

int main(){
  const_cast<int&&>(int(0));
}

Я не знаю, в чем разница, когда операндом является 0, int{0} и int(0) соответственно. На мой взгляд, все они prvalue типа int.

typedef int *A[3];
typedef const int *const CA[3];
int main(){
   A &&r2 = const_cast<A&&>(CA{});
}

Этот код является формальным примером expr.const.cast # 3. К сожалению, он отклонен Clang.

Не знаю, можно ли это рассматривать как дефект стандарта или некорректную реализацию Clang? Я не знаю, какова цель третьего маркера [expr.const.cast # 4], почему в нем специально упоминается prvalue типа класса? (Намерено ли оно сказать, что будет применяться только prvalue типа класса временная материализация к нему? Однако это явно противоречит примеру для prvalue типа массива).

  • CWG1965? Language Lawyer 01.03.2021
  • @LanguageLawyer Мне кажется, что всякий раз, когда glvalue ожидается как операнд оператора, общее правило expr # basic.lval-7 должен привести исходный операнд (prvalue) к glvalue, за исключением того, что правило явно запрещает это преобразование (временное преобразование материализации). В противном случае [expr # basic.lval-7] будет немного противоречивым. xmh0511 02.03.2021

c++language-lawyerconst-cast

Ответы

Ответ 1 · Serge Ballesta

Ключевым моментом здесь является если T1 - это тип класса. Тип int не является типом класса, поэтому 4.3 не применяется. Если бы вы использовали std::string, это сработало бы:

const std::string && x = const_cast<std::string&&>(std::string("foo") + "bar");

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы