Указывает ли спецификацию на С++, как типы выбираются в цепочке 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
вводится в одном месте и удаляется в другом.
Существуют ли какие-либо правила, определяющие, каким образом компилятор должен определить, какие типы использовать в цепочке литья? Если да, то где они? Если нет, является ли это дефектом в языке или существуют достаточные неявные правила, позволяющие однозначно определять все возможные броски, чтобы попробовать?
Ответы
Ответ 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
.