1
# if !defined(TS_NUMERIC_TYPE_HEADER)
2
# define TS_NUMERIC_TYPE_HEADER
6
Create a distinct type from a builtin numeric type.
8
This template class converts a basic type into a class, so that
9
instances of the class act like the basic type in normal use but
10
as a distinct type when evaluating overloads. This is very handy
11
when one has several distinct value types that map to the same
12
basic type. That means we can have overloads based on the type
13
even though the underlying basic type is the same. The second
14
template argument, X, is used only for distinguishing
15
instantiations of the template with the same base type. It doesn't
16
have to exist. One can declare an instantiation like
19
typedef NumericType<int, struct some_random_tag_name> some_random_type;
22
It is not necessary to ever mention some_random_tag_name
23
again. All we need is the entry in the symbol table.
25
Copyright 2010 Network Geographics, Inc.
27
Licensed under the Apache License, Version 2.0 (the "License");
28
you may not use this file except in compliance with the License.
29
You may obtain a copy of the License at
31
http://www.apache.org/licenses/LICENSE-2.0
33
Unless required by applicable law or agreed to in writing, software
34
distributed under the License is distributed on an "AS IS" BASIS,
35
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36
See the License for the specific language governing permissions and
37
limitations under the License.
45
template < typename T, typename X > class NumericType;
47
/// @cond NOT_DOCUMENTED
48
/** Support template for resolving operator ambiguity.
52
@internal This resolves a problem when @a T is not @c int. In
53
that case, because raw numbers are @c int the overloading rule
54
changes creates an ambiguity - gcc won't distinguish between class
55
methods and builtins because @c NumericType has a user conversion
56
to @a T. So signature <tt>(NumericType, T)</tt> and <tt>(T,
57
int)</tt> are considered equivalent. This defines the @c int
58
operators explicitly. We inherit it so if @a T is @c int, these
59
are silently overridden.
61
@internal Note that we don't have to provide an actual implementation
62
for these operators. Funky, isn't it?
65
typename T, ///< Base numeric type.
66
typename X ///< Distinguishing tag type.
67
> class NumericTypeIntOperators {
69
NumericType<T,X>& operator += ( int t );
70
NumericType<T,X>& operator -= ( int t );
72
// Must have const and non-const versions.
73
NumericType<T,X> operator + ( int t );
74
NumericType<T,X> operator - ( int t );
75
NumericType<T,X> operator + ( int t ) const;
76
NumericType<T,X> operator - ( int t ) const;
79
template < typename T, typename X > NumericType<T,X>
80
operator + ( int t, NumericTypeIntOperators<T,X> const& );
82
template < typename T, typename X > NumericType<T,X>
83
operator - ( int t, NumericTypeIntOperators<T,X> const& );
87
/** Numeric type template.
89
@internal One issue is that this is not a POD and so doesn't work
90
with @c printf. I will need to investigate what that would take.
93
typename T, ///< Base numeric type.
94
typename X ///< Distinguishing tag type.
95
> class NumericType : public NumericTypeIntOperators<T,X> {
97
typedef T raw_type; //!< Base builtin type.
98
typedef NumericType self; //!< Self reference type.
100
/// @cond NOT_DOCUMENTED
101
// Need to import these to avoid compiler problems.
102
using NumericTypeIntOperators<T,X>::operator +=;
103
using NumericTypeIntOperators<T,X>::operator -=;
104
using NumericTypeIntOperators<T,X>::operator +;
105
using NumericTypeIntOperators<T,X>::operator -;
108
/// Default constructor, uninitialized.
110
//! Construct from implementation type.
112
raw_type const t ///< Initialized value.
114
//! Assignment from implementation type.
115
NumericType & operator = (raw_type const t);
117
NumericType & operator = (self const& that);
119
/// User conversion to implementation type.
120
/// @internal If we have just a single const method conversion to a copy
121
/// of the @c raw_type then the stream operators don't work. Only a CR
122
/// conversion operator satisifies the argument matching.
123
operator raw_type const& () const { return _t; }
124
/// User conversion to implementation type.
125
operator raw_type& () { return _t; }
126
/// Explicit conversion to host type
127
raw_type raw() const { return _t; }
129
// User conversions to raw type provide the standard comparison operators.
130
self& operator += ( self const& that );
131
self& operator -= ( self const& that );
133
self& operator += ( raw_type t );
134
self& operator -= ( raw_type t );
136
self operator + ( self const& that );
137
self operator - ( self const& that );
139
self operator + ( raw_type t );
140
self operator - ( raw_type t );
143
self operator ++(int);
145
self operator --(int);
151
// Method definitions.
152
template < typename T, typename X > NumericType<T,X>::NumericType() { }
153
template < typename T, typename X > NumericType<T,X>::NumericType(raw_type const t) : _t(t) { }
154
template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator = (raw_type const t) { _t = t; return *this; }
155
template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator = (self const& that) { _t = that._t; return *this; }
157
template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator += ( self const& that ) { _t += that._t; return *this; }
158
template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator -= ( self const& that ) { _t -= that._t; return *this; }
159
template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator + ( self const& that ) { return self(_t + that._t); }
160
template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator - ( self const& that ) { return self(_t - that._t); }
162
template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator += ( raw_type t ) { _t += t; return *this; }
163
template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator -= ( raw_type t ) { _t -= t; return *this; }
164
template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator + ( raw_type t ) { return self(_t + t); }
165
template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator - ( raw_type t ) { return self(_t - t); }
167
template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator ++() { ++_t; return *this; }
168
template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator --() { --_t; return *this; }
169
template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator ++(int) { self tmp(*this); ++_t; return tmp; }
170
template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator --(int) { self tmp(*this); --_t; return tmp; }
172
template < typename T, typename X > NumericType<T,X> operator + ( T const& lhs, NumericType<T,X> const& rhs ) { return rhs + lhs; }
173
template < typename T, typename X > NumericType<T,X> operator - ( T const& lhs, NumericType<T,X> const& rhs ) { return NumericType<T,X>(lhs - rhs.raw()); }
175
/* ----------------------------------------------------------------------- */
176
} /* end namespace ts */
177
/* ----------------------------------------------------------------------- */
178
# endif // TS_NUMERIC_TYPE_HEADER