Подтвердить что ты не робот

Указывает ли спецификацию на С++, как типы выбираются в цепочке static_cast/const_cast, которая будет использоваться при создании C-стиля?

Этот вопрос касается того, что я заметил в спецификации С++, когда я пытался ответить на этот ранее, интригующий вопрос о приведениях в стиле C и преобразования типов.

Спецификация С++ рассказывает о приведениях в стиле C в разделе & section; 5.4. В нем говорится, что нотация заметок будет пытаться выполнить следующие действия в этом порядке до тех пор, пока не будет найдено, что это действительно:

  • const_cast
  • static_cast
  • static_cast, за которым следует const_cast
  • reinterpret_cast
  • reinterpret_cast, за которым следует const_cast.

Хотя у меня есть отличная интуитивная идея о том, что означает использовать static_cast, за которым следует const_cast (например, чтобы преобразовать a const Derived* в Base*, пройдя через const_cast<Base*>(static_cast<const Base*>(expr))), Я не вижу каких-либо формулировок в спецификации, говоря, что, в частности, следует использовать типы, используемые в серии static_cast/const_cast. В случае простых указателей это не так сложно, но, как видно из связанного вопроса, приведение может быть успешным, если дополнительный const вводится в одном месте и удаляется в другом.

Существуют ли какие-либо правила, определяющие, каким образом компилятор должен определить, какие типы использовать в цепочке литья? Если да, то где они? Если нет, является ли это дефектом в языке или существуют достаточные неявные правила, позволяющие однозначно определять все возможные броски, чтобы попробовать?

4b9b3361

Ответ 1

Если нет, является ли это дефектом в языке или существуют достаточные неявные правила, позволяющие однозначно определять все возможные броски, чтобы попробовать?

Как построить все типы, которые могут быть добавлены к целевому типу, используя только const_cast, т.е. все "промежуточные типы"?

Указанный целевой тип T, если static_cast не работает, укажите все позиции, в которые можно было бы добавить cv-квалификаторы, чтобы возвращаемый тип можно было вернуть на T на const_cast 1. Эскиз алгоритма: возьмите cv-разложение ([conv.qual]/1) T; каждый cv j может быть дополнен. Если T является ссылкой, мы можем увеличить квалификацию cv-рефери.

Теперь добавьте const volatile ко всем этим местам. Вызвать полученный тип CT. Попробуйте static_cast заменить выражение на CT. Если это работает, наша цепочка литья const_cast<T>(static_cast<CT>( e )).

Если это не сработает, вероятно, нет конверсии с использованием static_cast, за которым следует const_cast (я не углубился в глубокие углы разрешения перегрузки (ну, я имею, но не для этого вопроса)), Но мы могли бы использовать грубую силу, чтобы многократно удалять const/volatile и проверять каждый тип, если мы действительно хотели. Поэтому теоретически нет никакой двусмысленности или неопределенности; если есть какая-то цепочка для литья, ее можно определить. На практике алгоритм может быть сделан очень простым, так как, по-видимому, достаточно "максимально допустимого" типа, который мы можем построить из T.