Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error: pasting "operator" and "+" does not give a valid preprocessing token

I'm writing a small Float class in order to compare floats more easily(as we know, because of the float's precision). So I need to reload almost all operators that double has. I find there is too much repeats, such as operator+, operator-, operator* and operator/. They are similar. So I used a macro to reduce the code length. But when I complie it, it doesn't work. The error is:

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

Here is my code:

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(/)

And my g++ version is 4.4.3

here is the result of 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;}
like image 811
abcdabcd987 Avatar asked Apr 14 '12 03:04

abcdabcd987


2 Answers

## concatenates tokens to produce a single token; the result must be a valid single token. You don't need to do this for operator, as e.g. operator+ is not actually a single token.

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

Strictly speaking, you are producing a single token for the later one.

Preprocessors that are actually textual preprocessors instead of operating during tokenization, such as the one in GCC, are often lenient about this.

like image 174
geekosaur Avatar answered Oct 18 '22 01:10

geekosaur


You can't use the ## in the macro; the tokens pasted have to be identifiers.

The first of the two occurrences in the macro can simply be replaced with a space. The second is much more problematic. Superficially, you might get away with:

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

However, that is most certainly not defined behaviour; the x and the = are separate preprocessing tokens and won't (should not) be combined into a single token by the pre-processor. I suspect you will need to use:

#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(+, +=)
like image 28
Jonathan Leffler Avatar answered Oct 18 '22 03:10

Jonathan Leffler