简体   繁体   中英

C++ primitive type safety

Is there any computational overhead by implementing class wrapper to ensure type-safety on C primitive types? And if not, why those wrapper are not in the STL?

#include <iostream>

template< typename T >
class Safe
{
    template<typename K>
    friend std::ostream& operator << (std::ostream&, const Safe<K>& );

public:

    using Type = T;

    Safe( ) = default;

    explicit Safe(const T& value) : m_value(value){}

    Safe<T> operator +(const Safe<T>& other) const;
    Safe<T> operator -(const Safe<T>& other) const;
    Safe<T> operator *(const Safe<T>& other) const;
    Safe<T> operator /(const Safe<T>& other) const;
    Safe<T> operator %(const Safe<T>& other) const;

private:
    T m_value;
};

template<typename T>
inline Safe<T> Safe<T>::operator +(const Safe<T>& other) const
{
    return Safe<T>( this->m_value + other.m_value );
}

template<typename T>
inline Safe<T> Safe<T>::operator -(const Safe<T>& other) const
{
    return Safe<T>( this->m_value - other.m_value );
}

template<typename T>
inline Safe<T> Safe<T>::operator *(const Safe<T>& other) const
{
    return Safe<T>( this->m_value * other.m_value );
}

template<typename T>
inline Safe<T> Safe<T>::operator /(const Safe<T>& other) const
{
    return Safe<T>( this->m_value / other.m_value );
}

template<typename T>
inline Safe<T> Safe<T>::operator %(const Safe<T>& other) const
{
    return Safe<T>( this->m_value % other.m_value );
}

template<typename T>
inline std::ostream& operator << (std::ostream& os, const Safe<T>& number)
{
    return os << number.m_value;
}

using Int8 = Safe<std::int8_t>;
using Int16 = Safe<std::int16_t>;
using Int32 = Safe<std::int32_t>;
using Int64 = Safe<std::int64_t>;

using UInt8 = Safe<std::uint8_t>;
using UInt16 = Safe<std::uint16_t>;
using UInt32 = Safe<std::uint32_t>;
using UInt64 = Safe<std::uint64_t>;

using Int = Safe<signed int>;
using UInt = Safe<unsigned int>;

int main(int, char *[])
{
    Int32 a(5);
    Int32 b(2);
    Int64 ehi(5);
    Int64 bee(2);

    const auto c = a + b;
    const auto see = ehi + bee;

    /* will not compile: */
    /* const auto result = a + bee; */

    std::cout << c << std::endl;
    std::cout << see << std::endl;

    return 0;
}

The overhead is massive since every single operation can potentially overflow and only rarely will the compiler be able to optimise your checks out. Which is basically why range-checked types are not in the STL. Ada does apply such checks, and they were built into the language from the very start, it's not something that is impossible or inherently a bad idea.

But as others have said, it's not a good fit for C++. If you must do it, I advise that all data is held as doubles and not allowed to go beyond the range +/-FTL_MAX, and FLT_EPSILON is clamped to zero. All indices hold as signed int and be very careful in clamping to INT_MAX.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM