• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

NumericType.h

Go to the documentation of this file.
00001 # if !defined(TS_NUMERIC_TYPE_HEADER)
00002 # define TS_NUMERIC_TYPE_HEADER
00003 
00004 /** @file
00005 
00006     Create a distinct type from a builtin numeric type.
00007 
00008     This template class converts a basic type into a class, so that
00009     instances of the class act like the basic type in normal use but
00010     as a distinct type when evaluating overloads. This is very handy
00011     when one has several distinct value types that map to the same
00012     basic type. That means we can have overloads based on the type
00013     even though the underlying basic type is the same. The second
00014     template argument, X, is used only for distinguishing
00015     instantiations of the template with the same base type. It doesn't
00016     have to exist. One can declare an instantiation like
00017 
00018     @code
00019     typedef NumericType<int, struct some_random_tag_name> some_random_type;
00020     @endcode
00021 
00022     It is not necessary to ever mention some_random_tag_name
00023     again. All we need is the entry in the symbol table.
00024 
00025     @section license License
00026 
00027     Licensed to the Apache Software Foundation (ASF) under one
00028     or more contributor license agreements.  See the NOTICE file
00029     distributed with this work for additional information
00030     regarding copyright ownership.  The ASF licenses this file
00031     to you under the Apache License, Version 2.0 (the
00032     "License"); you may not use this file except in compliance
00033     with the License.  You may obtain a copy of the License at
00034 
00035     http://www.apache.org/licenses/LICENSE-2.0
00036 
00037     Unless required by applicable law or agreed to in writing, software
00038     distributed under the License is distributed on an "AS IS" BASIS,
00039     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00040     See the License for the specific language governing permissions and
00041     limitations under the License.
00042  */
00043 
00044 # include <limits>
00045 
00046 namespace ts {
00047 
00048 // Forward declare.
00049 template < typename T, typename X > class NumericType;
00050 
00051 /// @cond NOT_DOCUMENTED
00052 /** Support template for resolving operator ambiguity.
00053 
00054     Not for client use.
00055 
00056     @internal This resolves a problem when @a T is not @c int.  In
00057     that case, because raw numbers are @c int the overloading rule
00058     changes creates an ambiguity - gcc won't distinguish between class
00059     methods and builtins because @c NumericType has a user conversion
00060     to @a T. So signature <tt>(NumericType, T)</tt> and <tt>(T,
00061     int)</tt> are considered equivalent. This defines the @c int
00062     operators explicitly. We inherit it so if @a T is @c int, these
00063     are silently overridden.
00064 
00065     @internal Note that we don't have to provide an actual implementation
00066     for these operators. Funky, isn't it?
00067 */
00068 template <
00069   typename T, ///< Base numeric type.
00070   typename X ///< Distinguishing tag type.
00071 > class NumericTypeIntOperators {
00072 public:
00073     NumericType<T,X>& operator += ( int t );
00074     NumericType<T,X>& operator -= ( int t );
00075 
00076     // Must have const and non-const versions.
00077     NumericType<T,X> operator +  ( int t );
00078     NumericType<T,X> operator -  ( int t );
00079     NumericType<T,X> operator +  ( int t ) const;
00080     NumericType<T,X> operator -  ( int t ) const;
00081 };
00082 
00083 template < typename T, typename X > NumericType<T,X>
00084 operator + ( int t, NumericTypeIntOperators<T,X> const& );
00085 
00086 template < typename T, typename X > NumericType<T,X>
00087 operator - ( int t, NumericTypeIntOperators<T,X> const& );
00088 
00089 /// @endcond
00090 
00091 /** Numeric type template.
00092 
00093     @internal One issue is that this is not a POD and so doesn't work
00094     with @c printf. I will need to investigate what that would take.
00095  */
00096 template <
00097   typename T, ///< Base numeric type.
00098   typename X ///< Distinguishing tag type.
00099 > class NumericType : public NumericTypeIntOperators<T,X> {
00100 public:
00101     typedef T raw_type; //!< Base builtin type.
00102     typedef NumericType self; //!< Self reference type.
00103 
00104     /// @cond NOT_DOCUMENTED
00105     // Need to import these to avoid compiler problems.
00106     using NumericTypeIntOperators<T,X>::operator +=;
00107     using NumericTypeIntOperators<T,X>::operator -=;
00108     using NumericTypeIntOperators<T,X>::operator +;
00109     using NumericTypeIntOperators<T,X>::operator -;
00110     /// @endcond
00111 
00112     /// Default constructor, uninitialized.
00113     NumericType();
00114     //! Construct from implementation type.
00115     NumericType(
00116       raw_type const t ///< Initialized value.
00117     );
00118     //! Assignment from implementation type.
00119     NumericType & operator = (raw_type const t);
00120     //! Self assignment.
00121     NumericType & operator = (self const& that);
00122 
00123     /// User conversion to implementation type.
00124     /// @internal If we have just a single const method conversion to a copy
00125     /// of the @c raw_type then the stream operators don't work. Only a CR
00126     /// conversion operator satisifies the argument matching.
00127     operator raw_type const& () const { return _t; }
00128     /// User conversion to implementation type.
00129     operator raw_type& () { return _t; }
00130     /// Explicit conversion to host type
00131     raw_type raw() const { return _t; }
00132 
00133     // User conversions to raw type provide the standard comparison operators.
00134     self& operator += ( self const& that );
00135     self& operator -= ( self const& that );
00136 
00137     self& operator += ( raw_type t );
00138     self& operator -= ( raw_type t );
00139 
00140     self operator +  ( self const& that );
00141     self operator -  ( self const& that );
00142 
00143     self operator +  ( raw_type t );
00144     self operator -  ( raw_type t );
00145 
00146     self& operator ++();
00147     self operator ++(int);
00148     self& operator --();
00149     self operator --(int);
00150 
00151 private:
00152     raw_type   _t;
00153 };
00154 
00155 // Method definitions.
00156 template < typename T, typename X > NumericType<T,X>::NumericType() { }
00157 template < typename T, typename X > NumericType<T,X>::NumericType(raw_type const t) : _t(t) { }
00158 template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator = (raw_type const t) { _t = t; return *this; }
00159 template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator = (self const& that) { _t = that._t; return *this; }
00160 
00161 template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator += ( self const& that ) { _t += that._t; return *this; }
00162 template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator -= ( self const& that ) { _t -= that._t; return *this; }
00163 template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator +  ( self const& that ) { return self(_t + that._t); }
00164 template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator -  ( self const& that ) { return self(_t - that._t); }
00165 
00166 template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator += ( raw_type t ) { _t += t; return *this; }
00167 template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator -= ( raw_type t ) { _t -= t; return *this; }
00168 template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator +  ( raw_type t ) { return self(_t + t); }
00169 template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator -  ( raw_type t ) { return self(_t - t); }
00170 
00171 template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator ++() { ++_t; return *this; }
00172 template < typename T, typename X > NumericType<T,X>& NumericType<T,X>::operator --() { --_t; return *this; }
00173 template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator ++(int) { self tmp(*this); ++_t; return tmp; }
00174 template < typename T, typename X > NumericType<T,X> NumericType<T,X>::operator --(int) { self tmp(*this); --_t; return tmp; }
00175 
00176 template < typename T, typename X > NumericType<T,X> operator +  ( T const& lhs, NumericType<T,X> const& rhs ) { return rhs + lhs; }
00177 template < typename T, typename X > NumericType<T,X> operator -  ( T const& lhs, NumericType<T,X> const& rhs ) { return NumericType<T,X>(lhs - rhs.raw()); }
00178 
00179 /* ----------------------------------------------------------------------- */
00180 } /* end namespace ts */
00181 /* ----------------------------------------------------------------------- */
00182 # endif // TS_NUMERIC_TYPE_HEADER

Generated by  doxygen 1.7.1