Как реализовать функцию, которая безопасно преобразует любой больший тип в меньший тип в C++ с помощью шаблонов?

Я пытаюсь написать функцию, которая проверяет, может ли приводимая переменная соответствовать целевому типу, и assert(), если нет. Прямо сейчас это то, что я придумал. Я еще не проверял. Я хотел бы, чтобы шаблон определял тип передаваемой переменной автоматически, с чем-то вроде typeid, хотя я действительно не знаю, что такое typeid на самом деле. Это возможно? Кроме того, я не очень разбираюсь в шаблонах.

template<typename from_T, typename to_T>
static inline to_T safe_cast(from_T variable)
{
    assert(variable >= std::numeric_limits<to_T>::min());
    assert(variable <= std::numeric_limits<to_T>::max());

    return static_cast<to_T>(variable);
}

Что ж, если это действительно какая-то функция, которая уже делает это, о которой я не знаю, я буду рад услышать.


person Community    schedule 27.02.2021    source источник


Ответы (1)


Основные рекомендации C++ уже содержит gsl::narrow

// узкий() : проверенная версия узкого_каста(), которая выдает, если приведение изменило значение

Вы можете увидеть реализацию Microsoft здесь

// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
template <class T, class U>
    constexpr T narrow(U u) noexcept(false)
{
    constexpr const bool is_different_signedness =
        (std::is_signed<T>::value != std::is_signed<U>::value);

    const T t = narrow_cast<T>(u);

    if (static_cast<U>(t) != u || (is_different_signedness && ((t < T{}) != (u < U{}))))
    {
        throw narrowing_error{};
    }

    return t;
}

Вы можете увидеть объяснение реализации в этом сообщении SO (это для более старой версии реализации, но ничего существенно не изменилось, поэтому ответ по-прежнему актуален).

person bolov    schedule 27.02.2021