Generated on: Thu Mar 29 07:46:58 PDT 2012 for custom file set | ||
|
||
00001 // Copyright 2010-2012 Google 00002 // Licensed under the Apache License, Version 2.0 (the "License"); 00003 // you may not use this file except in compliance with the License. 00004 // You may obtain a copy of the License at 00005 // 00006 // http://www.apache.org/licenses/LICENSE-2.0 00007 // 00008 // Unless required by applicable law or agreed to in writing, software 00009 // distributed under the License is distributed on an "AS IS" BASIS, 00010 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00011 // See the License for the specific language governing permissions and 00012 // limitations under the License. 00013 00014 00015 // IntType is a simple template class mechanism for defining "logical" 00016 // integer-like class types that support many of the same functionalities 00017 // as native integer types, but which prevent assignment, construction, and 00018 // other operations from other similar integer-like types. Essentially, the 00019 // template class IntType<IntTypeName, ValueType> (where ValueType assumes 00020 // valid scalar types such as int, uint, int32, etc) has the additional 00021 // property that it cannot be assigned to or constructed from other IntTypes 00022 // or native integer types of equal or implicitly convertible type. 00023 // 00024 // The class is useful for preventing mingling of integer variables with 00025 // different logical roles or units. Unfortunately, C++ provides relatively 00026 // good type-safety for user-defined classes but not for integer types. It is 00027 // essentially up to the user to use nice variable names and comments to prevent 00028 // accidental mismatches, such as confusing a user-index with a group-index or a 00029 // time-in-milliseconds with a time-in-seconds. The use of typedefs are limited 00030 // in that regard as they do not enforce type-safety. 00031 // 00032 // USAGE ----------------------------------------------------------------------- 00033 // 00034 // DEFINE_INT_TYPE(IntTypeName, ValueType); 00035 // 00036 // where: 00037 // IntTypeName: is the desired (unique) name for the "logical" integer type. 00038 // ValueType: is one of the integral types: 00039 // (int, int64, short, long, char, unsigned version). 00040 // 00041 // DISALLOWED OPERATIONS / TYPE-SAFETY ENFORCEMENT ----------------------------- 00042 // 00043 // Consider these definitions and variable declarations: 00044 // DEFINE_INT_TYPE(GlobalDocID, int64); 00045 // DEFINE_INT_TYPE(LocalDocID, int64); 00046 // GlobalDocID global; 00047 // LocalDocID local; 00048 // 00049 // The class IntType prevents: 00050 // 00051 // 1) Assignments of other IntTypes with different IntTypeNames. 00052 // 00053 // global = local; <-- Fails to compile! 00054 // local = global; <-- Fails to compile! 00055 // 00056 // 2) Explicit/implicit conversion from an IntType to another IntType. 00057 // 00058 // LocalDocID l(global); <-- Fails to compile! 00059 // LocalDocID l = global; <-- Fails to compile! 00060 // 00061 // void GetGlobalDoc(GlobalDocID global) { } 00062 // GetGlobalDoc(global); <-- Compiles fine, types match! 00063 // GetGlobalDoc(local); <-- Fails to compile! 00064 // 00065 // 3) Implicit conversion from an IntType to a native integer type. 00066 // 00067 // void GetGlobalDoc(int64 global) { ... 00068 // GetGlobalDoc(global); <-- Fails to compile! 00069 // GetGlobalDoc(local); <-- Fails to compile! 00070 // 00071 // void GetLocalDoc(int32 local) { ... 00072 // GetLocalDoc(global); <-- Fails to compile! 00073 // GetLocalDoc(local); <-- Fails to compile! 00074 // 00075 // 00076 // SUPPORTED OPERATIONS -------------------------------------------------------- 00077 // 00078 // The following operators are supported: unary: ++ (both prefix and postfix), 00079 // +, -, ! (logical not), ~ (one's complement); comparison: ==, !=, <, <=, >, 00080 // >=; numerical: +, -, *, /; assignment: =, +=, -=, /=, *=; stream: <<. Each 00081 // operator allows the same IntTypeName and the ValueType to be used on 00082 // both left- and right-hand sides. 00083 // 00084 // It also supports an accessor value() returning the stored value as ValueType, 00085 // and a templatized accessor value<T>() method that serves as syntactic sugar 00086 // for static_cast<T>(var.value()). These accessors are useful when assigning 00087 // the stored value into protocol buffer fields and using it as printf args. 00088 // 00089 // The class also defines a hash functor that allows the IntType to be used 00090 // as key to hashable containers such as hash_map and hash_set. 00091 // 00092 // We suggest using the IntTypeIndexedContainer wrapper around STL 00093 // vector (see int-type-indexed-vector.h) if an IntType is intended 00094 // to be used as an index into these containers. These wrappers are 00095 // indexed in a type-safe manner using IntTypes to ensure type-safety. 00096 // 00097 // NB: this implementation does not attempt to abide by or enforce dimensional 00098 // analysis on these scalar types. 00099 // 00100 // EXAMPLES -------------------------------------------------------------------- 00101 // 00102 // DEFINE_INT_TYPE(GlobalDocID, int64); 00103 // GlobalDocID global = 3; 00104 // cout << global; <-- Prints 3 to stdout. 00105 // 00106 // for (GlobalDocID i(0); i < global; ++i) { 00107 // cout << i; 00108 // } <-- Print(ln)s 0 1 2 to stdout 00109 // 00110 // DEFINE_INT_TYPE(LocalDocID, int64); 00111 // LocalDocID local; 00112 // cout << local; <-- Prints 0 to stdout it default 00113 // initializes the value to 0. 00114 // 00115 // local = 5; 00116 // local *= 2; 00117 // LocalDocID l(local); 00118 // cout << l + local; <-- Prints 20 to stdout. 00119 // 00120 // GenericSearchRequest request; 00121 // request.set_doc_id(global.value()); <-- Uses value() to extract the value 00122 // from the IntType class. 00123 // 00124 // REMARKS --------------------------------------------------------------------- 00125 // 00126 // The following bad usage is permissible although discouraged. Essentially, it 00127 // involves using the value*() accessors to extract the native integer type out 00128 // of the IntType class. Keep in mind that the primary reason for the IntType 00129 // class is to prevent *accidental* mingling of similar logical integer types -- 00130 // and not type casting from one type to another. 00131 // 00132 // DEFINE_INT_TYPE(GlobalDocID, int64); 00133 // DEFINE_INT_TYPE(LocalDocID, int64); 00134 // GlobalDocID global; 00135 // LocalDocID local; 00136 // 00137 // global = local.value(); <-- Compiles fine. 00138 // 00139 // void GetGlobalDoc(GlobalDocID global) { ... 00140 // GetGlobalDoc(local.value()); <-- Compiles fine. 00141 // 00142 // void GetGlobalDoc(int64 global) { ... 00143 // GetGlobalDoc(local.value()); <-- Compiles fine. 00144 00145 #ifndef OR_TOOLS_BASE_INT_TYPE_H_ 00146 #define OR_TOOLS_BASE_INT_TYPE_H_ 00147 00148 #include <stddef.h> 00149 #include "base/hash.h" 00150 #include <iosfwd> 00151 #include <ostream> // NOLINT 00152 00153 #include "base/macros.h" 00154 00155 template <typename IntTypeName, typename _ValueType> class IntType; 00156 00157 // Defines the IntType using value_type and typedefs it to int_type_name. 00158 // The struct int_type_name ## _tag_ trickery is needed to ensure that a new 00159 // type is created per int_type_name. 00160 #define DEFINE_INT_TYPE(int_type_name, value_type) \ 00161 struct int_type_name ## _tag_ {}; \ 00162 typedef IntType<int_type_name ## _tag_, value_type> int_type_name; 00163 00164 // Holds a integral value (of type ValueType) and behaves as a 00165 // ValueType by exposing assignment, unary, comparison, and arithmetic 00166 // operators. 00167 // 00168 // The template parameter IntTypeName defines the name for the int type and must 00169 // be unique within a binary (the convenient DEFINE_INT_TYPE macro at the end of 00170 // the file generates a unique IntTypeName). The parameter ValueType defines 00171 // the integer type value (see supported list above). 00172 // 00173 // This class is NOT thread-safe. 00174 template <typename IntTypeName, typename _ValueType> 00175 class IntType { 00176 public: 00177 typedef _ValueType ValueType; // for non-member operators 00178 typedef IntType<IntTypeName, ValueType> ThisType; // Syntactic sugar. 00179 00180 public: 00181 // Default c'tor initializing value_ to 0. 00182 IntType() : value_(0) { } 00183 // C'tor explicitly initializing from a ValueType. 00184 explicit IntType(ValueType value) : value_(value) { } 00185 // IntType uses the default copy constructor and destructor. 00186 00187 // -- ACCESSORS -------------------------------------------------------------- 00188 // The class provides a value() accessor returning the stored ValueType value_ 00189 // as well as a templatized accessor that is just a syntactic sugar for 00190 // static_cast<T>(var.value()); 00191 ValueType value() const { return value_; } 00192 00193 template <typename ValType> 00194 ValType value() const { return static_cast<ValType>(value_); } 00195 00196 // -- UNARY OPERATORS -------------------------------------------------------- 00197 ThisType& operator++() { // prefix ++ 00198 ++value_; 00199 return *this; 00200 } 00201 const ThisType operator++(int v) { // postfix ++ 00202 ThisType temp(*this); 00203 ++value_; 00204 return temp; 00205 } 00206 ThisType& operator--() { // prefix -- 00207 --value_; 00208 return *this; 00209 } 00210 const ThisType operator--(int v) { // postfix -- 00211 ThisType temp(*this); 00212 --value_; 00213 return temp; 00214 } 00215 00216 bool operator!() const { return value_ == 0; } 00217 const ThisType operator+() const { return ThisType(value_); } 00218 const ThisType operator-() const { return ThisType(-value_); } 00219 const ThisType operator~() const { return ThisType(~value_); } 00220 00221 // -- ASSIGNMENT OPERATORS --------------------------------------------------- 00222 // We support the following assignment operators: =, +=, -=, *=, /=, <<=, >>= 00223 // and %= for both ThisType and ValueType. 00224 #define INT_TYPE_ASSIGNMENT_OP(op) \ 00225 ThisType& operator op(const ThisType& arg_value) { \ 00226 value_ op arg_value.value(); \ 00227 return *this; \ 00228 } \ 00229 ThisType& operator op(ValueType arg_value) { \ 00230 value_ op arg_value; \ 00231 return *this; \ 00232 } 00233 INT_TYPE_ASSIGNMENT_OP(=); 00234 INT_TYPE_ASSIGNMENT_OP(+=); 00235 INT_TYPE_ASSIGNMENT_OP(-=); 00236 INT_TYPE_ASSIGNMENT_OP(*=); 00237 INT_TYPE_ASSIGNMENT_OP(/=); 00238 INT_TYPE_ASSIGNMENT_OP(<<=); // NOLINT 00239 INT_TYPE_ASSIGNMENT_OP(>>=); // NOLINT 00240 INT_TYPE_ASSIGNMENT_OP(%=); 00241 #undef INT_TYPE_ASSIGNMENT_OP 00242 00243 private: 00244 // The integer value of type ValueType. 00245 ValueType value_; 00246 }; 00247 00248 // -- NON-MEMBER STREAM OPERATORS ---------------------------------------------- 00249 // We provide the << operator, primarily for logging purposes. Currently, there 00250 // seems to be no need for an >> operator. 00251 template <typename IntTypeName, typename ValueType> 00252 std::ostream& operator <<(std::ostream& os, // NOLINT 00253 IntType<IntTypeName, ValueType> arg) { 00254 return os << arg.value(); 00255 } 00256 00257 // -- NON-MEMBER ARITHMETIC OPERATORS ------------------------------------------ 00258 // We support only the +, -, *, and / operators with the same IntType and 00259 // ValueType types. The reason is to allow simple manipulation on these IDs 00260 // when used as indices in vectors and arrays. 00261 // 00262 // NB: Although it is possible to do IntType * IntType and IntType / IntType, 00263 // it is probably non-sensical from a dimensionality analysis perspective. 00264 #define INT_TYPE_ARITHMETIC_OP(op) \ 00265 template <typename IntTypeName, typename ValueType> \ 00266 static inline IntType<IntTypeName, ValueType> \ 00267 operator op(IntType<IntTypeName, ValueType> id_1, \ 00268 IntType<IntTypeName, ValueType> id_2) { \ 00269 id_1 op ## = id_2.value(); \ 00270 return id_1; \ 00271 } \ 00272 template <typename IntTypeName, typename ValueType> \ 00273 static inline IntType<IntTypeName, ValueType> \ 00274 operator op(IntType<IntTypeName, ValueType> id, \ 00275 typename IntType<IntTypeName, ValueType>::ValueType arg_val) { \ 00276 id op ## = arg_val; \ 00277 return id; \ 00278 } \ 00279 template <typename IntTypeName, typename ValueType> \ 00280 static inline IntType<IntTypeName, ValueType> \ 00281 operator op(typename IntType<IntTypeName, ValueType>::ValueType arg_val, \ 00282 IntType<IntTypeName, ValueType> id) { \ 00283 IntType<IntTypeName, ValueType> obj(arg_val); \ 00284 obj op ## = id.value(); \ 00285 return obj; \ 00286 } 00287 INT_TYPE_ARITHMETIC_OP(+); 00288 INT_TYPE_ARITHMETIC_OP(-); 00289 INT_TYPE_ARITHMETIC_OP(*); 00290 INT_TYPE_ARITHMETIC_OP(/); 00291 INT_TYPE_ARITHMETIC_OP(<<); // NOLINT 00292 INT_TYPE_ARITHMETIC_OP(>>); // NOLINT 00293 INT_TYPE_ARITHMETIC_OP(%); 00294 #undef INT_TYPE_ARITHMETIC_OP 00295 00296 // -- NON-MEMBER COMPARISON OPERATORS ------------------------------------------ 00297 // Static inline comparison operators. We allow all comparison operators among 00298 // the following types (OP \in [==, !=, <, <=, >, >=]: 00299 // IntType<IntTypeName, ValueType> OP IntType<IntTypeName, ValueType> 00300 // IntType<IntTypeName, ValueType> OP ValueType 00301 // ValueType OP IntType<IntTypeName, ValueType> 00302 #define INT_TYPE_COMPARISON_OP(op) \ 00303 template <typename IntTypeName, typename ValueType> \ 00304 static inline bool operator op(IntType<IntTypeName, ValueType> id_1, \ 00305 IntType<IntTypeName, ValueType> id_2) { \ 00306 return id_1.value() op id_2.value(); \ 00307 } \ 00308 template <typename IntTypeName, typename ValueType> \ 00309 static inline bool operator op( \ 00310 IntType<IntTypeName, ValueType> id, \ 00311 typename IntType<IntTypeName, ValueType>::ValueType val) { \ 00312 return id.value() op val; \ 00313 } \ 00314 template <typename IntTypeName, typename ValueType> \ 00315 static inline bool operator op( \ 00316 typename IntType<IntTypeName, ValueType>::ValueType val, \ 00317 IntType<IntTypeName, ValueType> id) { \ 00318 return val op id.value(); \ 00319 } 00320 INT_TYPE_COMPARISON_OP(==); // NOLINT 00321 INT_TYPE_COMPARISON_OP(!=); // NOLINT 00322 INT_TYPE_COMPARISON_OP(<); // NOLINT 00323 INT_TYPE_COMPARISON_OP(<=); // NOLINT 00324 INT_TYPE_COMPARISON_OP(>); // NOLINT 00325 INT_TYPE_COMPARISON_OP(>=); // NOLINT 00326 #undef INT_TYPE_COMPARISON_OP 00327 00328 // Allows it to be used as a key to hashable containers. 00329 #if !defined(SWIG) 00330 #if !defined(_MSC_VER) 00331 namespace __gnu_cxx { 00332 template <typename IntTypeName, typename ValueType> 00333 struct hash<IntType<IntTypeName, ValueType> > { 00334 size_t operator()(const IntType<IntTypeName, ValueType>& idx) const { 00335 return static_cast<size_t>(idx.value()); 00336 } 00337 }; 00338 } // namespace __gnu_cxx 00339 #endif // !defined(_MSC_VER) 00340 #endif // !defined(SWIG) 00341 00342 #endif // OR_TOOLS_BASE_INT_TYPE_H_