Chris@16
|
1 #ifndef CONSTRAINED_VALUE_HPP___
|
Chris@16
|
2 #define CONSTRAINED_VALUE_HPP___
|
Chris@16
|
3
|
Chris@16
|
4 /* Copyright (c) 2002,2003 CrystalClear Software, Inc.
|
Chris@16
|
5 * Use, modification and distribution is subject to the
|
Chris@16
|
6 * Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
7 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 * Author: Jeff Garland
|
Chris@101
|
9 * $Date$
|
Chris@16
|
10 */
|
Chris@16
|
11
|
Chris@16
|
12 #include <exception>
|
Chris@16
|
13 #include <stdexcept>
|
Chris@16
|
14 #include <boost/config.hpp>
|
Chris@16
|
15 #include <boost/throw_exception.hpp>
|
Chris@16
|
16 #include <boost/mpl/if.hpp>
|
Chris@16
|
17 #include <boost/type_traits/is_base_of.hpp>
|
Chris@16
|
18
|
Chris@16
|
19 namespace boost {
|
Chris@16
|
20
|
Chris@16
|
21 //! Namespace containing constrained_value template and types
|
Chris@16
|
22 namespace CV {
|
Chris@16
|
23 //! Represent a min or max violation type
|
Chris@16
|
24 enum violation_enum {min_violation, max_violation};
|
Chris@16
|
25
|
Chris@16
|
26 //! A template to specify a constrained basic value type
|
Chris@16
|
27 /*! This template provides a quick way to generate
|
Chris@16
|
28 * an integer type with a constrained range. The type
|
Chris@16
|
29 * provides for the ability to specify the min, max, and
|
Chris@16
|
30 * and error handling policy.
|
Chris@16
|
31 *
|
Chris@16
|
32 * <b>value policies</b>
|
Chris@16
|
33 * A class that provides the range limits via the min and
|
Chris@16
|
34 * max functions as well as a function on_error that
|
Chris@16
|
35 * determines how errors are handled. A common strategy
|
Chris@16
|
36 * would be to assert or throw and exception. The on_error
|
Chris@16
|
37 * is passed both the current value and the new value that
|
Chris@16
|
38 * is in error.
|
Chris@16
|
39 *
|
Chris@16
|
40 */
|
Chris@16
|
41 template<class value_policies>
|
Chris@16
|
42 class constrained_value {
|
Chris@16
|
43 public:
|
Chris@16
|
44 typedef typename value_policies::value_type value_type;
|
Chris@16
|
45 // typedef except_type exception_type;
|
Chris@16
|
46 constrained_value(value_type value) : value_((min)())
|
Chris@16
|
47 {
|
Chris@16
|
48 assign(value);
|
Chris@16
|
49 }
|
Chris@16
|
50 constrained_value& operator=(value_type v)
|
Chris@16
|
51 {
|
Chris@16
|
52 assign(v);
|
Chris@16
|
53 return *this;
|
Chris@16
|
54 }
|
Chris@16
|
55 //! Return the max allowed value (traits method)
|
Chris@16
|
56 static value_type max BOOST_PREVENT_MACRO_SUBSTITUTION () {return (value_policies::max)();}
|
Chris@16
|
57 //! Return the min allowed value (traits method)
|
Chris@16
|
58 static value_type min BOOST_PREVENT_MACRO_SUBSTITUTION () {return (value_policies::min)();}
|
Chris@16
|
59 //! Coerce into the representation type
|
Chris@16
|
60 operator value_type() const {return value_;}
|
Chris@16
|
61 protected:
|
Chris@16
|
62 value_type value_;
|
Chris@16
|
63 private:
|
Chris@16
|
64 void assign(value_type value)
|
Chris@16
|
65 {
|
Chris@16
|
66 //adding 1 below gets rid of a compiler warning which occurs when the
|
Chris@16
|
67 //min_value is 0 and the type is unsigned....
|
Chris@16
|
68 if (value+1 < (min)()+1) {
|
Chris@16
|
69 value_policies::on_error(value_, value, min_violation);
|
Chris@16
|
70 return;
|
Chris@16
|
71 }
|
Chris@16
|
72 if (value > (max)()) {
|
Chris@16
|
73 value_policies::on_error(value_, value, max_violation);
|
Chris@16
|
74 return;
|
Chris@16
|
75 }
|
Chris@16
|
76 value_ = value;
|
Chris@16
|
77 }
|
Chris@16
|
78 };
|
Chris@16
|
79
|
Chris@16
|
80 //! Template to shortcut the constrained_value policy creation process
|
Chris@16
|
81 template<typename rep_type, rep_type min_value,
|
Chris@16
|
82 rep_type max_value, class exception_type>
|
Chris@16
|
83 class simple_exception_policy
|
Chris@16
|
84 {
|
Chris@16
|
85 struct exception_wrapper : public exception_type
|
Chris@16
|
86 {
|
Chris@16
|
87 // In order to support throw_exception mechanism in the BOOST_NO_EXCEPTIONS mode,
|
Chris@16
|
88 // we'll have to provide a way to acquire std::exception from the exception being thrown.
|
Chris@16
|
89 // However, we cannot derive from it, since it would make it interceptable by this class,
|
Chris@16
|
90 // which might not be what the user wanted.
|
Chris@16
|
91 operator std::out_of_range () const
|
Chris@16
|
92 {
|
Chris@16
|
93 // TODO: Make the message more descriptive by using arguments to on_error
|
Chris@16
|
94 return std::out_of_range("constrained value boundary has been violated");
|
Chris@16
|
95 }
|
Chris@16
|
96 };
|
Chris@16
|
97
|
Chris@16
|
98 typedef typename mpl::if_<
|
Chris@16
|
99 is_base_of< std::exception, exception_type >,
|
Chris@16
|
100 exception_type,
|
Chris@16
|
101 exception_wrapper
|
Chris@16
|
102 >::type actual_exception_type;
|
Chris@16
|
103
|
Chris@16
|
104 public:
|
Chris@16
|
105 typedef rep_type value_type;
|
Chris@16
|
106 static rep_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return min_value; }
|
Chris@16
|
107 static rep_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return max_value; }
|
Chris@16
|
108 static void on_error(rep_type, rep_type, violation_enum)
|
Chris@16
|
109 {
|
Chris@16
|
110 boost::throw_exception(actual_exception_type());
|
Chris@16
|
111 }
|
Chris@16
|
112 };
|
Chris@16
|
113
|
Chris@16
|
114
|
Chris@16
|
115
|
Chris@16
|
116 } } //namespace CV
|
Chris@16
|
117
|
Chris@16
|
118
|
Chris@16
|
119
|
Chris@16
|
120
|
Chris@16
|
121 #endif
|