📄 syncedprimitive.h
字号:
/* Author: Tobi Vollebregt */
#ifndef SYNCEDPRIMITIVE_H
#define SYNCEDPRIMITIVE_H
#if defined(SYNCDEBUG) || defined(SYNCCHECK)
#include "SyncChecker.h" // for CSyncedPrimitiveBase (if SYNCCHECK is defined)
#include "SyncDebugger.h" // for CSyncedPrimitiveBase (if SYNCDEBUG is defined)
#include "Upcast.h" // for UPCAST macro
/*
Unfortunately I have to resort to preprocessor magic to expand all functions
for all C++ primitive types. Templates don't work because this confuses the
compiler, as that opens up too much possible conversions, and hence results
in errors like the following on GCC 4:
error: ISO C++ says that these are ambiguous, even though the worst conversion
for the first is better than the worst conversion for the second:
note: candidate 1: operator==(int, int) <built-in>
note: candidate 2: bool operator==(T, SyncedPrimitive) [with T = short unsigned int]
*/
#ifdef UPCAST_USE_64_BIT_TYPES
#define FOR_EACH_PRIMITIVE_TYPE \
DO(signed char) \
DO(signed short) \
DO(signed int) \
DO(signed long) \
DO(Sint64) \
DO(unsigned char) \
DO(unsigned short) \
DO(unsigned int) \
DO(unsigned long) \
DO(Uint64) \
DO(float) \
DO(double) \
DO(long double) \
DO(bool)
#else // UPCAST_USE_64_BIT_TYPES
#define FOR_EACH_PRIMITIVE_TYPE \
DO(signed char) \
DO(signed short) \
DO(signed int) \
DO(signed long) \
DO(unsigned char) \
DO(unsigned short) \
DO(unsigned int) \
DO(unsigned long) \
DO(float) \
DO(double) \
DO(long double) \
DO(bool)
#endif // !UPCAST_USE_64_BIT_TYPES
/** \p SyncedPrimitive class. Variables of this type are automagically
downcasted to their value_type, preventing them to be implicitly used for
anything but carefully selected places. The goal of this class is to call
\p CSyncedPrimitiveBase::Sync() on each write to the data member \p x. */
template <class T> struct SyncedPrimitive : public CSyncedPrimitiveBase {
T x;
void Sync(const char* op) {CSyncedPrimitiveBase::Sync((void*)&x, sizeof(T), op);}
SyncedPrimitive(): x(0) {}
/* unary functions */
bool operator!() const {return !x;}
UPCAST(T,T) operator~() const {return ~x;}
UPCAST(T,T) operator-() const {return -x;}
/* prefix/postfix increment/decrement */
UPCAST(T,T) operator++() {++x; Sync("++pre"); return x;}
UPCAST(T,T) operator--() {--x; Sync("--pre"); return x;}
UPCAST(T,T) operator++(int) {T r=x++; Sync("post++"); return r;}
UPCAST(T,T) operator--(int) {T r=x--; Sync("post--"); return r;}
/* assignment */
template<class U> SyncedPrimitive(const SyncedPrimitive<U>& f): x(f.x) {Sync("copy");}
template<class U> SyncedPrimitive& operator=(const SyncedPrimitive<U>& f) {x=f.x; Sync("="); return *this;}
template<class U> SyncedPrimitive& operator+=(const SyncedPrimitive<U>& f) {x+=f.x; Sync("+="); return *this;}
template<class U> SyncedPrimitive& operator-=(const SyncedPrimitive<U>& f) {x-=f.x; Sync("-="); return *this;}
template<class U> SyncedPrimitive& operator*=(const SyncedPrimitive<U>& f) {x*=f.x; Sync("*="); return *this;}
template<class U> SyncedPrimitive& operator/=(const SyncedPrimitive<U>& f) {x/=f.x; Sync("/="); return *this;}
template<class U> SyncedPrimitive& operator%=(const SyncedPrimitive<U>& f) {x%=f.x; Sync("%="); return *this;}
template<class U> SyncedPrimitive& operator&=(const SyncedPrimitive<U>& f) {x&=f.x; Sync("&="); return *this;}
template<class U> SyncedPrimitive& operator|=(const SyncedPrimitive<U>& f) {x|=f.x; Sync("|="); return *this;}
template<class U> SyncedPrimitive& operator^=(const SyncedPrimitive<U>& f) {x^=f.x; Sync("^="); return *this;}
template<class U> SyncedPrimitive& operator<<=(const SyncedPrimitive<U>& f) {x<<=f.x; Sync("<<="); return *this;}
template<class U> SyncedPrimitive& operator>>=(const SyncedPrimitive<U>& f) {x>>=f.x; Sync(">>="); return *this;}
#define DO(T) \
SyncedPrimitive(T f): x(f) {Sync("copy" #T);} \
SyncedPrimitive& operator=(const T f) {x=f; Sync("=" #T); return *this; } \
SyncedPrimitive& operator+=(const T f) {x+=f; Sync("+=" #T); return *this; } \
SyncedPrimitive& operator-=(const T f) {x-=f; Sync("-=" #T); return *this; } \
SyncedPrimitive& operator*=(const T f) {x*=f; Sync("*=" #T); return *this; } \
SyncedPrimitive& operator/=(const T f) {x/=f; Sync("/=" #T); return *this; } \
SyncedPrimitive& operator%=(const T f) {x%=f; Sync("%=" #T); return *this; } \
SyncedPrimitive& operator&=(const T f) {x&=f; Sync("&=" #T); return *this; } \
SyncedPrimitive& operator|=(const T f) {x|=f; Sync("|=" #T); return *this; } \
SyncedPrimitive& operator^=(const T f) {x^=f; Sync("^=" #T); return *this; } \
SyncedPrimitive& operator<<=(const T f) {x<<=f; Sync("<<=" #T); return *this; } \
SyncedPrimitive& operator>>=(const T f) {x>>=f; Sync(">>=" #T); return *this; }
FOR_EACH_PRIMITIVE_TYPE
#undef DO
operator T () const { return x; }
};
template<class U, class V> inline UPCAST(U,V) operator+(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x+g.x;}
template<class U, class V> inline UPCAST(U,V) operator-(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x-g.x;}
template<class U, class V> inline UPCAST(U,V) operator*(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x*g.x;}
template<class U, class V> inline UPCAST(U,V) operator/(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x/g.x;}
template<class U, class V> inline UPCAST(U,V) operator%(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x%g.x;}
template<class U, class V> inline UPCAST(U,V) operator&(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x&g.x;}
template<class U, class V> inline UPCAST(U,V) operator|(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x|g.x;}
template<class U, class V> inline UPCAST(U,V) operator^(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x^g.x;}
template<class U, class V> inline UPCAST(U,V) operator<<(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x<<g.x;}
template<class U, class V> inline UPCAST(U,V) operator>>(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x>>g.x;}
template<class U, class V> inline bool operator<(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x<g.x;}
template<class U, class V> inline bool operator>(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x>g.x;}
template<class U, class V> inline bool operator<=(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x<=g.x;}
template<class U, class V> inline bool operator>=(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x>=g.x;}
template<class U, class V> inline bool operator==(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x==g.x;}
template<class U, class V> inline bool operator!=(const SyncedPrimitive<U>& f, const SyncedPrimitive<V>& g) {return f.x!=g.x;}
#define DO(T) \
template<class U> inline UPCAST(T,U) operator+(const SyncedPrimitive<U>& f, const T g) {return f.x+g;} \
template<class U> inline UPCAST(T,U) operator-(const SyncedPrimitive<U>& f, const T g) {return f.x-g;} \
template<class U> inline UPCAST(T,U) operator*(const SyncedPrimitive<U>& f, const T g) {return f.x*g;} \
template<class U> inline UPCAST(T,U) operator/(const SyncedPrimitive<U>& f, const T g) {return f.x/g;} \
template<class U> inline UPCAST(T,U) operator%(const SyncedPrimitive<U>& f, const T g) {return f.x%g;} \
template<class U> inline UPCAST(T,U) operator&(const SyncedPrimitive<U>& f, const T g) {return f.x&g;} \
template<class U> inline UPCAST(T,U) operator|(const SyncedPrimitive<U>& f, const T g) {return f.x|g;} \
template<class U> inline UPCAST(T,U) operator^(const SyncedPrimitive<U>& f, const T g) {return f.x^g;} \
template<class U> inline UPCAST(T,U) operator<<(const SyncedPrimitive<U>& f, const T g) {return f.x<<g;} \
template<class U> inline UPCAST(T,U) operator>>(const SyncedPrimitive<U>& f, const T g) {return f.x>>g;} \
template<class V> inline UPCAST(T,V) operator+(const T f, const SyncedPrimitive<V>& g) {return f+g.x;} \
template<class V> inline UPCAST(T,V) operator-(const T f, const SyncedPrimitive<V>& g) {return f-g.x;} \
template<class V> inline UPCAST(T,V) operator*(const T f, const SyncedPrimitive<V>& g) {return f*g.x;} \
template<class V> inline UPCAST(T,V) operator/(const T f, const SyncedPrimitive<V>& g) {return f/g.x;} \
template<class V> inline UPCAST(T,V) operator%(const T f, const SyncedPrimitive<V>& g) {return f%g.x;} \
template<class V> inline UPCAST(T,V) operator&(const T f, const SyncedPrimitive<V>& g) {return f&g.x;} \
template<class V> inline UPCAST(T,V) operator|(const T f, const SyncedPrimitive<V>& g) {return f|g.x;} \
template<class V> inline UPCAST(T,V) operator^(const T f, const SyncedPrimitive<V>& g) {return f^g.x;} \
template<class V> inline UPCAST(T,V) operator<<(const T f, const SyncedPrimitive<V>& g) {return f<<g.x;} \
template<class V> inline UPCAST(T,V) operator>>(const T f, const SyncedPrimitive<V>& g) {return f>>g.x;} \
template<class U> inline bool operator<(const SyncedPrimitive<U>& f, const T g) {return f.x<g;} \
template<class U> inline bool operator>(const SyncedPrimitive<U>& f, const T g) {return f.x>g;} \
template<class U> inline bool operator<=(const SyncedPrimitive<U>& f, const T g) {return f.x<=g;} \
template<class U> inline bool operator>=(const SyncedPrimitive<U>& f, const T g) {return f.x>=g;} \
template<class U> inline bool operator==(const SyncedPrimitive<U>& f, const T g) {return f.x==g;} \
template<class U> inline bool operator!=(const SyncedPrimitive<U>& f, const T g) {return f.x!=g;} \
template<class V> inline bool operator<(const T f, const SyncedPrimitive<V>& g) {return f<g.x;} \
template<class V> inline bool operator>(const T f, const SyncedPrimitive<V>& g) {return f>g.x;} \
template<class V> inline bool operator<=(const T f, const SyncedPrimitive<V>& g) {return f<=g.x;} \
template<class V> inline bool operator>=(const T f, const SyncedPrimitive<V>& g) {return f>=g.x;} \
template<class V> inline bool operator==(const T f, const SyncedPrimitive<V>& g) {return f==g.x;} \
template<class V> inline bool operator!=(const T f, const SyncedPrimitive<V>& g) {return f!=g.x;}
FOR_EACH_PRIMITIVE_TYPE
#undef DO
template<class T> inline T min(const T f, const SyncedPrimitive<T>& g) {return std::min(f,g.x);}
template<class T> inline T min(const SyncedPrimitive<T>& f, const T g) {return std::min(f.x,g);}
template<class T> inline T max(const T f, const SyncedPrimitive<T>& g) {return std::max(f,g.x);}
template<class T> inline T max(const SyncedPrimitive<T>& f, const T g) {return std::max(f.x,g);}
typedef SyncedPrimitive< bool > SyncedBool;
typedef SyncedPrimitive< signed char > SyncedSchar;
typedef SyncedPrimitive< signed short > SyncedSshort;
typedef SyncedPrimitive< signed int > SyncedSint;
typedef SyncedPrimitive< signed long > SyncedSlong;
typedef SyncedPrimitive< unsigned char > SyncedUchar;
typedef SyncedPrimitive< unsigned short > SyncedUshort;
typedef SyncedPrimitive< unsigned int > SyncedUint;
typedef SyncedPrimitive< unsigned long > SyncedUlong;
typedef SyncedPrimitive< float > SyncedFloat;
typedef SyncedPrimitive< double > SyncedDouble;
typedef SyncedPrimitive< long double > SyncedLongDouble;
#ifdef UPCAST_USE_64_BIT_TYPES
typedef SyncedPrimitive< Sint64 > SyncedSint64;
typedef SyncedPrimitive< Uint64 > SyncedUint64;
#endif // UPCAST_USE_64_BIT_TYPES
#else // SYNCDEBUG || SYNCCHECK
// 64 bit types are missing here because they made AIs depend on SDL
// (SDL_types.h specifically)
typedef bool SyncedBool;
typedef signed char SyncedSchar;
typedef signed short SyncedSshort;
typedef signed int SyncedSint;
typedef signed long SyncedSlong;
typedef unsigned char SyncedUchar;
typedef unsigned short SyncedUshort;
typedef unsigned int SyncedUint;
typedef unsigned long SyncedUlong;
typedef float SyncedFloat;
typedef double SyncedDouble;
typedef long double SyncedLongDouble;
#endif // !SYNCDEBUG && !SYNCCHECK
#endif // SYNCEDPRIMITIVE_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -