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 хоть.

http://ideone.com/TxYose

Другие вопросы по тегам