Есть ли "безопасная" альтернатива static_cast?

Есть ли "безопасная" альтернатива static_cast в С++ static_cast или библиотека, которая реализует эту функциональность?

Под "безопасным" я подразумеваю, что приведение должно допускать только броски, которые не теряют точность. Таким образом, приведение из int64_t в int32_t только в том случае, если число помещается в int32_t а также сообщается об ошибке.

Ответ 1

Там gsl::narrow

узкий //narrow<T>(x) - static_cast<T>(x) если static_cast<T>(x) == x или он вызывает narrowing_error

Ответ 2

У вас есть случай использования.

Предполагаемое использование 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 обычно приводит только к предупреждению), поэтому убедитесь, что вы используете правильные флаги, чтобы заставить предупреждения обрабатываться как ошибки.

Ответ 3

Вы можете создавать свои собственные с помощью 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 здесь означает "определено во время компиляции".