Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use a numeric_cast policy?

Tags:

c++

boost

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?

like image 903
dbbd Avatar asked Feb 23 '15 15:02

dbbd


1 Answers

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.

like image 196
Alper Avatar answered Oct 17 '22 16:10

Alper