dbbd
dbbd

Reputation: 894

How do I use a numeric_cast policy?

So I have my own policy for uint64_t to uint32_t numeric cast

struct MyOverflowHandlerPolicy
{
    void operator() ( boost::numeric::range_check_result ) {
         std::cout << "MyOverflowHandlerPolicy called" << std::endl;
         throw boost::numeric::positive_overflow();
    };
} ;

How do I get it to be used by boost::numeric_cast?

Upvotes: 5

Views: 815

Answers (1)

Alper
Alper

Reputation: 13220

In order to use numeric_cast, numeric_cast_traits specialization should defined on each type conversions. These specializations are already defined with default values for the built-in numeric types. It is possible to disable the generation of specializations for built-in types by defining BOOST_NUMERIC_CONVERSION_RELAX_BUILT_IN_CAST_TRAITS (details).

Here is a small running sample.

#include <iostream>
#include <stdexcept>

#define BOOST_NUMERIC_CONVERSION_RELAX_BUILT_IN_CAST_TRAITS
#include <boost/numeric/conversion/cast.hpp>

using namespace std;

struct YourOverflowHandlerPolicy
{
    void operator() ( boost::numeric::range_check_result r ) { 
         cout << "YourOverflowHandlerPolicy called" << endl;
         if (r != boost::numeric::cInRange) {
            throw logic_error("Not in range!");
         }   
    };  
};

namespace boost { namespace numeric {
template <>
struct numeric_cast_traits<uint32_t, uint64_t>
{
    typedef YourOverflowHandlerPolicy overflow_policy;
    typedef UseInternalRangeChecker   range_checking_policy;
    typedef Trunc<uint64_t>           rounding_policy;
};

template <>
struct numeric_cast_traits<uint64_t, uint32_t>
{
    typedef YourOverflowHandlerPolicy overflow_policy;
    typedef UseInternalRangeChecker   range_checking_policy;
    typedef Trunc<uint32_t>           rounding_policy;
};
}} //namespace boost::numeric;

int main()
{
    try {
        cout << boost::numeric_cast<uint32_t>((uint64_t)1) <<  endl; // OK
        cout << boost::numeric_cast<uint32_t>((uint64_t)1<<31) <<  endl; // OK
        cout << boost::numeric_cast<uint32_t>((uint64_t)1<<32) <<  endl; // Exception
    } catch (...) {
        cout << "exception" << endl;
    }   

    return 0;
}

Output:

YourOverflowHandlerPolicy called
1
YourOverflowHandlerPolicy called
2147483648
YourOverflowHandlerPolicy called
exception

Note: I have boost release 1.55.0, I don't know the minimum release level to get it compiled but it isn't compiled with 1.46.0. So, please check your boost release and update if necessary.

Upvotes: 6

Related Questions