static_cast между примитивными ссылками
Использует static_cast
конвертировать из const unsigned char&
в const unsigned long long&
определены?
constexpr unsigned char arr[sizeof(unsigned long long)]{ 1 };
constexpr bool value = static_cast<const unsigned long long&>(arr[0]) == 1;
Бросить в int main(){}
и это компилируется без ошибок или предупреждений на Coliru, Ideone и VS2015. Это на самом деле безопасно, или это небезопасно, но не обязательно, чтобы выдать ошибку?
БОНУС: Я этого не ожидал arr[0]
будет постоянным выражением, но с использованием value
как константное выражение работает без ошибок. Это потому что arr
такое массив?
2 ответа
Я думаю, что это покрыто [expr.static.cast]/4 в C++14:
Выражение
e
может быть явно преобразован в типT
используяstatic_cast
формыstatic_cast<T>(e)
если декларацияT t(e);
правильно сформирован, для некоторой придуманной временной переменнойt
, Эффект такого явного преобразования аналогичен выполнению объявления и инициализации, а затем использованию временной переменной в качестве результата преобразования.
Это определяет ваш код как эквивалент:
constexpr unsigned char arr[sizeof(unsigned long long)]{ 1 };
const unsigned long long &t (arr[0]);
constexpr bool value = (t == 1);
Вторая строка теперь знакома: инициализация константной ссылки из значения другого (не связанного со ссылками) типа разрешена в [dcl.init.ref]/5:
Если
T1
это неклассный тип, временный тип cv1T1
создается и инициализируется копией из выражения инициализатора. Ссылка затем привязывается к временному.
* Это не определено, потому что вы используете один тип через ссылку на другой. * Вы использовали приведение, поэтому предполагается, что компилятор будет доверять вам, если сможет выполнить это приведение. * Обычно это работает так, как вы ожидаете, за исключением того, что я сомневаюсь, что ценность будет верна для большинства архитектур.
И на самом деле я думаю, что то, что здесь происходит, заключается в том, что const & to cast, к которому вы применяете, привязывается к временному, или будет, если это произойдет во время выполнения. Так что да, вы должны получить 1
от стоимости. char
1 будет скопирован в unsigned long long
и const & будет связываться с этим. Я не думаю, что он будет привязан к массиву, который вы создали. Это было бы абсолютно безопасно, и вы можете игнорировать большинство из вышеперечисленного.
Вы можете проверить эту мысль немного, возможно, попытавшись преобразовать в lvalue. Вы бы не должны были ваши данные быть constexpr
хоть.