#ifndef CONSTRAINED_VALUE_HPP___ | |
#define CONSTRAINED_VALUE_HPP___ | |
/* Copyright (c) 2002,2003 CrystalClear Software, Inc. | |
* Use, modification and distribution is subject to the | |
* Boost Software License, Version 1.0. (See accompanying | |
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) | |
* Author: Jeff Garland | |
* $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ | |
*/ | |
#include <exception> | |
#include <stdexcept> | |
#include <boost/config.hpp> | |
#include <boost/throw_exception.hpp> | |
#include <boost/mpl/if.hpp> | |
#include <boost/type_traits/is_base_of.hpp> | |
namespace boost { | |
//! Namespace containing constrained_value template and types | |
namespace CV { | |
//! Represent a min or max violation type | |
enum violation_enum {min_violation, max_violation}; | |
//! A template to specify a constrained basic value type | |
/*! This template provides a quick way to generate | |
* an integer type with a constrained range. The type | |
* provides for the ability to specify the min, max, and | |
* and error handling policy. | |
* | |
* <b>value policies</b> | |
* A class that provides the range limits via the min and | |
* max functions as well as a function on_error that | |
* determines how errors are handled. A common strategy | |
* would be to assert or throw and exception. The on_error | |
* is passed both the current value and the new value that | |
* is in error. | |
* | |
*/ | |
template<class value_policies> | |
class constrained_value { | |
public: | |
typedef typename value_policies::value_type value_type; | |
// typedef except_type exception_type; | |
constrained_value(value_type value) : value_((min)()) | |
{ | |
assign(value); | |
} | |
constrained_value& operator=(value_type v) | |
{ | |
assign(v); | |
return *this; | |
} | |
//! Return the max allowed value (traits method) | |
static value_type max BOOST_PREVENT_MACRO_SUBSTITUTION () {return (value_policies::max)();} | |
//! Return the min allowed value (traits method) | |
static value_type min BOOST_PREVENT_MACRO_SUBSTITUTION () {return (value_policies::min)();} | |
//! Coerce into the representation type | |
operator value_type() const {return value_;} | |
protected: | |
value_type value_; | |
private: | |
void assign(value_type value) | |
{ | |
//adding 1 below gets rid of a compiler warning which occurs when the | |
//min_value is 0 and the type is unsigned.... | |
if (value+1 < (min)()+1) { | |
value_policies::on_error(value_, value, min_violation); | |
return; | |
} | |
if (value > (max)()) { | |
value_policies::on_error(value_, value, max_violation); | |
return; | |
} | |
value_ = value; | |
} | |
}; | |
//! Template to shortcut the constrained_value policy creation process | |
template<typename rep_type, rep_type min_value, | |
rep_type max_value, class exception_type> | |
class simple_exception_policy | |
{ | |
struct exception_wrapper : public exception_type | |
{ | |
// In order to support throw_exception mechanism in the BOOST_NO_EXCEPTIONS mode, | |
// we'll have to provide a way to acquire std::exception from the exception being thrown. | |
// However, we cannot derive from it, since it would make it interceptable by this class, | |
// which might not be what the user wanted. | |
operator std::out_of_range () const | |
{ | |
// TODO: Make the message more descriptive by using arguments to on_error | |
return std::out_of_range("constrained value boundary has been violated"); | |
} | |
}; | |
typedef typename mpl::if_< | |
is_base_of< std::exception, exception_type >, | |
exception_type, | |
exception_wrapper | |
>::type actual_exception_type; | |
public: | |
typedef rep_type value_type; | |
static rep_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return min_value; } | |
static rep_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return max_value; } | |
static void on_error(rep_type, rep_type, violation_enum) | |
{ | |
boost::throw_exception(actual_exception_type()); | |
} | |
}; | |
} } //namespace CV | |
#endif |