Disable templetized operators by default
authorMarco Costalba <mcostalba@gmail.com>
Thu, 19 Aug 2010 06:38:13 +0000 (07:38 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Thu, 19 Aug 2010 12:48:41 +0000 (13:48 +0100)
To avoid nasty bugs due to silently overriding of
common operator we enable the templates on a type
by type base using partial template specialization.

No functional change, zero overhead at runtime.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/book.cpp
src/color.h
src/depth.h
src/direction.h
src/piece.h
src/square.h
src/types.h
src/value.h

index dbd037885711c191b23d53622a6b6aa8db75dba9..ad0d406d343d6b3889132a28c728727394ed5924 100644 (file)
@@ -366,7 +366,7 @@ void Book::open(const string& fName) {
 
   // Get the book size in number of entries
   seekg(0, ios::end);
-  bookSize = tellg() / EntrySize;
+  bookSize = long(tellg()) / EntrySize;
   seekg(0, ios::beg);
 
   if (!good())
index c946a548e2ebedded0618845cf3a81bf0f0fac8a..c6897a2e3b9ad53f9607aa294fb523889900bc54 100644 (file)
@@ -21,6 +21,7 @@
 #if !defined(COLOR_H_INCLUDED)
 #define COLOR_H_INCLUDED
 
+#include "types.h"
 
 ////
 //// Types
@@ -37,6 +38,8 @@ enum SquareColor {
   LIGHT
 };
 
+ENABLE_OPERATORS_ON(Color);
+
 
 ////
 //// Inline functions
index ab88f652a4bda753fdeeaac42478027767920276..f77dd0d3d926ac20dda6f5c48560c528db64ed63 100644 (file)
@@ -21,6 +21,8 @@
 #if !defined(DEPTH_H_INCLUDED)
 #define DEPTH_H_INCLUDED
 
+#include "types.h"
+
 ////
 //// Types
 ////
@@ -33,5 +35,6 @@ enum Depth {
   DEPTH_NONE = -127 * ONE_PLY
 };
 
+ENABLE_OPERATORS_ON(Depth);
 
 #endif // !defined(DEPTH_H_INCLUDED)
index 399a628ba21c9bcbcfa50366e0dd54334df3c4db..0500840a4277ac02240755ebf899b4f335e4038c 100644 (file)
@@ -45,6 +45,8 @@ enum SignedDirection {
   SIGNED_DIR_NONE = 8
 };
 
+ENABLE_OPERATORS_ON(SignedDirection);
+
 
 ////
 //// Variables
index 40a01e1005401ee7c807c22746484f77945b52ad..6592de1a8bbf1d2b04a34b51f9a24c706ef673c1 100644 (file)
@@ -43,6 +43,9 @@ enum Piece {
   BP = 9, BN = 10, BB = 11, BR = 12, BQ = 13, BK = 14, PIECE_NONE = 16
 };
 
+ENABLE_OPERATORS_ON(PieceType);
+ENABLE_OPERATORS_ON(Piece);
+
 
 ////
 //// Constants
index d539e0054df8ed99ca4497f1b39fe6202adb4c8d..4d427e8e1072d5400bf5c89e3aaea15cde0802ef 100644 (file)
@@ -64,6 +64,11 @@ enum SquareDelta {
   DELTA_NN = 020, DELTA_NNE = 021
 };
 
+ENABLE_OPERATORS_ON(Square);
+ENABLE_OPERATORS_ON(File);
+ENABLE_OPERATORS_ON(Rank);
+ENABLE_OPERATORS_ON(SquareDelta);
+
 
 ////
 //// Constants
index 226d76e44d63a3607a8c2e45452871522c2e0460..a85aa7f7292bea9417f8daecf0634f676bab61b1 100644 (file)
@@ -112,43 +112,61 @@ inline void __cpuid(int CPUInfo[4], int)
 
 // Templetized operators used by enum types like Depth, Piece, Square and so on.
 // We don't want to write the same inline for each different enum. Note that we
-// pass by value (to silence scaring warnings on volatiles), so you really should
-// use only enum types with these functions to avoid hidden copies.
+// pass by value to silence scaring warnings when using volatiles.
+// Because these templates override common operators and are included in all the
+// files, there is a possibility that the compiler silently performs some unwanted
+// overrides. To avoid possible very nasty bugs the templates are disabled by default
+// and must be enabled for each type on a case by case base. The enabling trick
+// uses template specialization, namely we just declare following struct.
+template<typename T> struct TempletizedOperator;
+
+// Then to enable the enum type we use following macro that defines a specialization
+// of TempletizedOperator for the given enum T. Here is defined typedef Not_Enabled.
+// Name of typedef is chosen to produce somewhat informative compile error messages.
+#define ENABLE_OPERATORS_ON(T)  \
+        template<> struct TempletizedOperator<T> { typedef T Not_Enabled; }
+
+// Finally we use macro OK(T) to check if type T is enabled. The macro simply
+// tries to use Not_Enabled, if was not previously defined a compile error occurs.
+// The check is done fully at compile time and there is zero overhead at runtime.
+#define OK(T) typedef typename TempletizedOperator<T>::Not_Enabled Type
 
 template<typename T>
-inline T operator+ (const T d1, const T d2) { return T(int(d1) + int(d2)); }
+inline T operator+ (const T d1, const T d2) { OK(T); return T(int(d1) + int(d2)); }
 
 template<typename T>
-inline T operator- (const T d1, const T d2) { return T(int(d1) - int(d2)); }
+inline T operator- (const T d1, const T d2) { OK(T); return T(int(d1) - int(d2)); }
 
 template<typename T>
-inline T operator* (int i, const T d) { return T(i * int(d)); }
+inline T operator* (int i, const T d) { OK(T); return T(i * int(d)); }
 
 template<typename T>
-inline T operator* (const T d, int i) { return T(int(d) * i); }
+inline T operator* (const T d, int i) { OK(T); return T(int(d) * i); }
 
 template<typename T>
-inline T operator/ (const T d, int i) { return T(int(d) / i); }
+inline T operator/ (const T d, int i) { OK(T); return T(int(d) / i); }
 
 template<typename T>
-inline T operator- (const T d) { return T(-int(d)); }
+inline T operator- (const T d) { OK(T); return T(-int(d)); }
 
 template<typename T>
-inline void operator++ (T& d, int) { d = T(int(d) + 1); }
+inline void operator++ (T& d, int) { OK(T); d = T(int(d) + 1); }
 
 template<typename T>
-inline void operator-- (T& d, int) { d = T(int(d) - 1); }
+inline void operator-- (T& d, int) { OK(T); d = T(int(d) - 1); }
 
 template<typename T>
-inline void operator+= (T& d1, const T d2) { d1 = d1 + d2; }
+inline void operator+= (T& d1, const T d2) { OK(T); d1 = d1 + d2; }
 
 template<typename T>
-inline void operator-= (T& d1, const T d2) { d1 = d1 - d2; }
+inline void operator-= (T& d1, const T d2) { OK(T); d1 = d1 - d2; }
 
 template<typename T>
-inline void operator*= (T& d, int i) { d = T(int(d) * i); }
+inline void operator*= (T& d, int i) { OK(T); d = T(int(d) * i); }
 
 template<typename T>
-inline void operator/= (T& d, int i) { d = T(int(d) / i); }
+inline void operator/= (T& d, int i) { OK(T); d = T(int(d) / i); }
+
+#undef OK
 
 #endif // !defined(TYPES_H_INCLUDED)
index d47ad544d2e4df6a877ae45ce5126c7df1d89907..d86a8bb90017126a02acbae20211107fc3a501ab 100644 (file)
@@ -50,6 +50,8 @@ enum Value {
   VALUE_ENSURE_SIGNED = -1
 };
 
+ENABLE_OPERATORS_ON(Value);
+
 
 enum ScaleFactor {
   SCALE_FACTOR_ZERO   = 0,
@@ -65,7 +67,13 @@ enum ScaleFactor {
 
 // Compiler is free to choose the enum type as long as can keep
 // its data, so ensure Score to be an integer type.
-enum Score { ENSURE_32_BITS_SIZE_P = (1 << 16), ENSURE_32_BITS_SIZE_N = -(1 << 16)};
+enum Score {
+    ENSURE_32_BITS_SIZE_P =  (1 << 16),
+    ENSURE_32_BITS_SIZE_N = -(1 << 16)
+};
+
+ENABLE_OPERATORS_ON(Score);
+
 
 // Extracting the _signed_ lower and upper 16 bits it not so trivial
 // because according to the standard a simple cast to short is