Ответ 1
Там gsl::narrow
узкий //
narrow<T>(x)
-static_cast<T>(x)
еслиstatic_cast<T>(x) == x
или он вызываетnarrowing_error
Есть ли "безопасная" альтернатива static_cast
в С++ static_cast
или библиотека, которая реализует эту функциональность?
Под "безопасным" я подразумеваю, что приведение должно допускать только броски, которые не теряют точность. Таким образом, приведение из int64_t
в int32_t
только в том случае, если число помещается в int32_t
а также сообщается об ошибке.
Там gsl::narrow
узкий //
narrow<T>(x)
-static_cast<T>(x)
еслиstatic_cast<T>(x) == x
или он вызываетnarrowing_error
У вас есть случай использования.
Предполагаемое использование static_cast
(и других C++ -стилей) должно указывать намерения программиста. Когда вы пишете auto value = static_cast<int32_t>(value_64);
, вы говорите "Да, я очень * намереваюсь", чтобы понизить это значение, возможно, усекая его, когда я выполняю это задание ". В результате компилятор, который, возможно, был склонен жаловаться на это преобразование при обычных обстоятельствах (например, если бы вы написали int32_t value = value_64;
) вместо этого int32_t value = value_64;
"хорошо, программист сказал мне, что это то, что они намеревались почему они лгут мне? и будет автоматически компилировать код.
Если вы хотите, чтобы ваш C++ код, чтобы предупредить или бросить ошибку на небезопасные преобразования, вам нужно явно не использовать static_cast
, const_cast
, reinterpret_cast
, и пусть компилятор делать свою работу. У компиляторов есть флаги, которые изменяют, как обрабатываются предупреждения (downcasting int64_t
to int32_t
обычно приводит только к предупреждению), поэтому убедитесь, что вы используете правильные флаги, чтобы заставить предупреждения обрабатываться как ошибки.
Вы можете создавать свои собственные с помощью sfinae. Вот пример:
template <typename T, typename U>
typename std::enable_if<sizeof(T) >= sizeof(U),T>::type
safe_static_cast(U&& val)
{
return static_cast<T>(val);
}
int main()
{
int32_t y = 2;
std::cout << safe_static_cast<int32_t>(y) << std::endl;
std::cout << safe_static_cast<int16_t>(y) << std::endl; // compile error
}
Это будет скомпилировано, только если размер, который вы выбрали, → = размер источника.
Попробуйте здесь
Вы можете усложнить это, используя numeric_limits для других типов и type_traits.
Обратите внимание, что мое решение - это решение для компиляции, потому что вы задали вопрос о static_cast
, где static здесь означает "определено во время компиляции".