我正在编写一个小的 Float 类,以便更容易地比较浮点数(正如我们所知,因为浮点数的精度)。所以我需要重新加载几乎所有 double 的运算符。我发现有太多的重复,例如 operator + , operator - , operator * 和 operator / 。它们很相似。所以我使用宏来减少代码长度。但是当我对它进行编译时,它不起作用。错误是:
happy.cc:24:1: error: pasting "operator" and "+" does not give a valid preprocessing token
happy.cc:25:1: error: pasting "operator" and "-" does not give a valid preprocessing token
happy.cc:26:1: error: pasting "operator" and "*" does not give a valid preprocessing token
happy.cc:27:1: error: pasting "operator" and "/" does not give a valid preprocessing token
这是我的代码:
struct Float
{
typedef double size_type;
static const size_type EPS = 1e-8;
private:
size_type x;
public:
Float(const size_type value = .0): x(value) { }
Float& operator+=(const Float& rhs) { x += rhs.x; return *this; }
Float& operator-=(const Float& rhs) { x -= rhs.x; return *this; }
Float& operator*=(const Float& rhs) { x *= rhs.x; return *this; }
Float& operator/=(const Float& rhs) { x /= rhs.x; return *this; }
};
#define ADD_ARITHMETIC_OPERATOR(x) \
inline const Float operator##x(const Float& lhs, const Float& rhs)\
{\
Float result(lhs);\
return result x##= rhs;\
}
ADD_ARITHMETIC_OPERATOR(+)
ADD_ARITHMETIC_OPERATOR(-)
ADD_ARITHMETIC_OPERATOR(*)
ADD_ARITHMETIC_OPERATOR(/)
我的g ++版本是4.4.3
这是g ++ -E的结果:
struct Float
{
typedef double size_type;
static const size_type EPS(1e-8);
private:
size_type x;
public:
Float(const size_type value = .0): x(value) { }
Float& operator+=(const Float& rhs) { x += rhs.x; return *this; }
Float& operator-=(const Float& rhs) { x -= rhs.x; return *this; }
Float& operator*=(const Float& rhs) { x *= rhs.x; return *this; }
Float& operator/=(const Float& rhs) { x /= rhs.x; return *this; }
};
inline const Float operator+(const Float& lhs, const Float& rhs){ Float result(lhs); return result += rhs;}
inline const Float operator-(const Float& lhs, const Float& rhs){ Float result(lhs); return result -= rhs;}
inline const Float operator*(const Float& lhs, const Float& rhs){ Float result(lhs); return result *= rhs;}
inline const Float operator/(const Float& lhs, const Float& rhs){ Float result(lhs); return result /= rhs;}
答案 0 :(得分:14)
##
连接令牌以生成单个令牌;结果必须是有效的单个令牌。您不需要为operator
执行此操作,例如operator+
实际上并不是一个令牌。
#define ADD_ARITHMETIC_OPERATOR(x) \
inline const Float operator x(const Float& lhs, const Float& rhs)\
{\
Float result(lhs);\
return result x##= rhs;\
}
严格地说, 为后者生成一个令牌。
实际上是文本预处理器而不是在标记化期间运行的预处理器(例如GCC中的预处理器)通常对此很宽松。
答案 1 :(得分:3)
您无法在宏中使用##
;粘贴的令牌必须是标识符。
宏中两次出现的第一次可以简单地用空格替换。第二个问题更多。从表面上看,你可能会逃避:
#define ADD_ARITHMETIC_OPERATOR(x) \
inline const Float operator x(const Float& lhs, const Float& rhs)\
{\
Float result(lhs);\
return result x= rhs;\
}
然而,这肯定是没有定义的行为; x
和=
是单独的预处理令牌,并且不会(不应该)由预处理器组合成单个令牌。我怀疑你需要使用:
#define ADD_ARITHMETIC_OPERATOR(x, y) \
inline const Float operator x(const Float& lhs, const Float& rhs)\
{\
Float result(lhs);\
return result y rhs;\
}
ADD_ARITHMETIC_OPERATOR(+, +=)