C++宏元编程

7
我有以下代码片段:
Vec& Vec::operator+=(const double x)
{
    return apply([x](double y) {return x + y;});
}

Vec& Vec::operator-=(const double x)
{
    return apply([x](double y) {return x - y;});
}

Vec& Vec::operator*=(const double x)
{
    return apply([x](double y) {return x * y;});
}

Vec& Vec::operator/=(const double x)
{
    return apply([x](double y) {return x / y;});
}

这些方法只是操作符号不同。是否有一种使用宏来简化编写这些方法的方式?


1
你尝试过什么吗? - Lightness Races in Orbit
我考虑使用类似于#define operate(op) Niz& Niz::operator##op=(const double x) { return apply([x](double y) {return x ##op y;}); }这样的东西,但是由于需要替换的字符是运算符而不是字面量,所以这是不允许的。 - Igor Ševo
1
不可以这样做,因为你错误地使用了 #### 用于连接宏参数以形成完整的 C++ 标记(例如 +=)。你不能只是在每个宏参数使用前面写上它。 - Lightness Races in Orbit
4
看起来你们的操作符有问题:似乎“-=”和“/=”操作符不是从每个元素中减去x并将每个元素除以x,而是从x中减去每个元素,并将x除以每个元素。 - Walter
@Walter:这是一个很好的观察。你说得对。谢谢。 - Igor Ševo
1
不客气。顺便说一下,向量之间的这些运算符应该由元素之间的相似运算符实现,即使用+=+=而不是+。此外,/=更有效地实现为operator*=(1/x):节省了dim-1个除法(比乘法更昂贵)。 - Walter
2个回答

7

是的,这很容易:

#define CREATE_OPERATOR(OP) \
  Vec& Vec::operator OP##= (const double x) \
  { return apply([x](double y) { return x OP y; }); }

CREATE_OPERATOR(+)
CREATE_OPERATOR(-)
CREATE_OPERATOR(*)
CREATE_OPERATOR(/)

当然,如果您需要多次重复使用此操作符符号列表,可以使用X宏技巧来实现: operators.hxx
OPERATOR(+)
OPERATOR(-)
OPERATOR(*)
OPERATOR(/)

#undef OPERATOR

你的代码

#define OPERATOR(OP) \
  /* same as above */

#include "operators.hxx"

1
呃,一个文件中有#define,但是在另一个文件中却有#undef?! - Lightness Races in Orbit
1
@LightnessRacesinOrbit 我相信X宏基本上是唯一可以这样做的情况。 - Angew is no longer proud of SO

5
似乎相当琐碎?
#define D(O) \
    Vec& Vec::operator O ## = (const double x) \
    { return apply([x](double y) {return x O y;}); }

D(+)
D(-)
D(*)
D(/)

#undef

##将参数与=“粘合”在一起,这是必需的,因为+=-=等都是原子标记。其余部分由宏的神奇处理。

(证明其编译)

顺便说一下,你所有的运算符都错了;应该写成y O x而不是x O y


一字母标识符获胜。 - LogicStuff
@LogicStuff,关于长度为零的标识符,我猜你是这个意思吧? - SergeyA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接