5

我正在编写一个小的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;}
4

2 回答 2

16

##连接标记以产生单个标记;结果必须是有效的单个令牌。您不需要为 执行此操作operator,因为 egoperator+实际上不是单个令牌。

#define ADD_ARITHMETIC_OPERATOR(x) \
inline const Float operator x(const Float& lhs, const Float& rhs)\
{\
  Float result(lhs);\
  return result x##= rhs;\
}

严格来说,您正在为后一个令牌生成一个令牌。

实际上是文本预处理器而不是在标记化期间运行的预处理器,例如 GCC 中的预处理器,通常对此很宽容。

于 2012-04-14T03:49:56.930 回答
3

您不能##在宏中使用;粘贴的标记必须是标识符。

宏中的两次出现中的第一次可以简单地替换为空格。第二个问题要多得多。从表面上看,你可能会逃脱:

#define ADD_ARITHMETIC_OPERATOR(x) \
inline const Float operator x(const Float& lhs, const Float& rhs)\
{\
  Float result(lhs);\
  return result x= rhs;\
}

但是,这肯定不是定义的行为;thex和 the=是单独的预处理标记,不会(不应该)被预处理器组合成单个标记。我怀疑您将需要使用:

#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(+, +=)
于 2012-04-14T03:54:38.870 回答