是否可以使用任意字符作为运算符?

时间:2015-03-04 09:09:31

标签: c++ operators

作为先前的说明:这不是我想要达到的目标;更多 - 这是一个与它是否真的有关的问题。

N.B。我理解(并且已经使用过)C ++中的运算符重写。例如:

std::ostream& operator<<(std::ostream& os, const T& obj){ return os; }

是否可以定义自定义ASCII字符作为运算符?

例如,从简单的意义上讲:使用严重重音(`)作为std :: pow的'别名'。

因此,以下陈述将是有效/可实现的:

std::cout << 2`3 << std::endl;

>> 8

2 个答案:

答案 0 :(得分:70)

您不能引入语法中不存在的字符,例如您提到的反引号。但是有一个"named operator" trick,您可以使用它来引入“命名运算符”来实现以下语法:

std::cout << (2 <Pow> 3) << std::endl;

这个技巧依赖于为自定义类型重载<>,如下所示:

const struct PowOperator {} Pow;

struct PowInvoker
{
  int lhs;
};

PowInvoker operator< (int lhs, PowOperator)
{
  return {lhs};
}

int operator> (PowInvoker lhs, int rhs)
{
  return std::pow(lhs.lhs, rhs);
}

int main()
{
  std::cout << (2 <Pow> 3) << std::endl;
}

[Live example]

请注意,您不能影响这些命名运算符的优先级:它们具有与<<=>>=相同的优先级。如果您需要不同的优先级,则必须使用不同的分隔符(可能不太可读)。


<强>声明

上面的技巧是“聪明”的代码,它几乎是滥用C ++语法。我把这个问题假设为一个假设的“可能的东西”,并回答了一个同样假设的“这就是”。我会建议在实践中使用它来解决诸如替换std::pow或提供“新颖”语法这样的微不足道的问题。上面提到的运算符优先警告是一个原因;对结构的一般不熟悉是另一种。代码质量是以代码生成的WTF数量来衡量的(越少越好),这个技巧会产生一大堆(以及那些大的)。

它仍有其用途:用于创建特定于域的语言。编程中存在将DSL嵌入到C ++代码中的情况;在这种情况下(在这种情况下)我会考虑使用它。

答案 1 :(得分:10)

不,那是不可能的。即使在预处理器级别,您也受到形成有效预处理器标记和宏名称的字符的限制,然后语言语法修复了该语言中的运算符集。