你能用 C++ 创建自定义运算符吗?
是否可以创建一个自定义运算符,以便您可以执行类似的操作?
if ("Hello, world!" contains "Hello") ...
注意:这是一个与“这是一个好主意吗……”不同的问题;)
Is it possible to make a custom operator so you can do things like this?
if ("Hello, world!" contains "Hello") ...
Note: this is a separate question from "Is it a good idea to..." ;)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
是的! (嗯,有点)
有一些公开可用的工具可以帮助您。两者都使用预处理器代码生成来创建实现自定义运算符的模板。这些运算符由一个或多个内置运算符与标识符一起组成。
由于这些实际上并不是自定义运算符,而仅仅是运算符重载的技巧,因此有一些警告:
_
、o
或类似的简单字母数字。CustomOperators
当我为此目的开发自己的库时(见下文),我遇到了这个项目。以下是创建
avg
运算符的示例:IdOp
开头为 纯粹无聊的练习成为我自己对这个问题的看法。这是一个类似的例子:
主要区别
Yes! (well, sort of)
There are a couple publicly available tools to help you out. Both use preprocessor code generation to create templates which implement the custom operators. These operators consist of one or more built-in operators in conjunction with an identifier.
Since these aren't actually custom operators, but merely tricks of operator overloading, there are a few caveats:
_
,o
or similarly simple alphanumerics.CustomOperators
While I was working on my own library for this purpose (see below) I came across this project. Here is an example of creating an
avg
operator:IdOp
What started as an exercise in pure frivolity became my own take on this problem. Here's a similar example:
Key Differences
Sander Stoks 在'句法阿斯巴甜' 中彻底探讨了一种方法,它允许您使用格式如下:
本质上,您需要一个带有运算符“<”的代理对象和“>”超载。代理完成所有工作; “包含”可以只是一个没有自己的行为或数据的单例。
There's a method thoroughly explored in 'Syntactic Aspartame' by Sander Stoks that would allow you to use the following format:
In essence, you need a proxy object with the operators '<' and '>' overloaded. The proxy does all of the work; 'contains' can just be a singleton with no behavior or data of its own.
我创建了以下两个宏:
,您只需定义自定义运算符,如下例所示:
设置运算符后,您可以将其用作预定义运算符:
警告
然后 这是一个有趣的练习,它只是展示了启用宏的预编译器是多么糟糕。添加像这样的自定义运算符可以很容易地产生一种元语言。尽管我们知道 C++ 的设计有多糟糕(最重要的是考虑到它最初被设想为 C 的一组扩展),但我们不应该改变它。如果您不能使用标准 C++(这是让其他人可以理解代码的唯一方法),那么您应该切换到另一种语言,该语言可以按照您希望的方式进行操作。语言有数千种 — 无需乱用 C++ 来使其与众不同。
简短说明:您不应该使用此代码。您应该避免使用宏,除非仅以与内联方法相同的方式使用。
I've created the following two macros:
Then, you'd have just to define your custom operator as in the following example:
Once a time you've set your operator up, you can use it as a predefined operator:
Warning
While this has been an interesting exercise, it merely demonstrates how bad is to have a macro–enabled precompiler. Adding custom operators like this can easily lead to a sort of metalanguage. Although we know how badly is C++ designed (most of all considering that it was first conceived as a set of extensions for C), we shouldn't be changing it. If you can't use standard C++, which is the only way to keep the code understandable by other people, you should just switch to another language that makes what you wish to do the way you'd like. There are thousands languages — no need to mess around with C++ to make it different.
SHORTLY: You just shouldn't be using this code. You should refrain from using macros unless when only used the same way as inline methods.
更准确地说,C++ 本身仅支持创建现有操作的新重载,而不支持创建新运算符。有些语言(例如,ML 及其大多数后代)确实允许您创建全新的运算符,但 C++ 不是其中之一。
从表面上看,(至少)另一个答案中提到的 CustomOperators 库也不支持完全自定义的运算符。至少如果我没有正确理解的话,它(在内部)将您的自定义运算符转换为现有运算符的重载。这使事情变得更容易,但牺牲了一些灵活性——例如,当您在 ML 中创建新运算符时,您可以为其赋予与任何内置运算符不同的优先级。
To be a bit more accurate, C++ itself only supports creating new overloads of existing operations, NOT creating new operators. There are languages (e.g., ML and most of its descendants) that do allow you to create entirely new operators, but C++ is not one of them.
From the looks of things, (at least) the CustomOperators library mentioned in the other answer doesn't support entirely custom operators either. At least if I'm reading things correctly, it's (internally) translating your custom operator into an overload of an existing operator. That makes things easier, at the expense of some flexibility -- for example, when you create a new operator in ML, you can give it precedence different from that of any built-in operator.
从技术上来说,不。也就是说,您无法扩展
operator+
、operator-
等集合。但你在例子中提出的是另一回事。您想知道是否存在“contains”的定义,使得string-literal "contains" string-literal
是一个具有非平凡逻辑的表达式(#define contains "" 是一个简单的情况)。
可以采用
string-literal X string-literal
形式的表达式并不多。这是因为字符串文字本身就是表达式。因此,您正在寻找expr X expr
形式的语言规则。其中有很多,但它们都是运算符的规则,并且这些规则不适用于字符串。尽管实现很明显,"Hello, " + "world"
并不是一个有效的表达式。那么, X 还可以在string-literal X string-literal
中出现吗?它本身不可能是一个表达式。它不能是类型名称、typedef 名称或模板名称。它不能是函数名称。它实际上只能是一个宏,这是仅存的命名实体。为此,请参阅“是(嗯,有点)”答案。Technically, no. That is to say, you can't extend the set of
operator+
,operator-
, etcetera. But what you're proposing in your example is something else. You are wondering if there is a definition of "contains" such thatstring-literal "contains" string-literal
is an expression, with non-trivial logic (#define contains ""
being the trivial case).There are not many expressions that can have the form
string-literal X string-literal
. This is because string literals themselves are expressions. So, you're looking for a language rule of the formexpr X expr
. There are quite a few of those, but they're all rules for operators, and those don't work on strings. Despite the obvious implementation,"Hello, " + "world"
is not a valid expression. So, what else can X be instring-literal X string-literal
? It can't be a expression itself. It can't be a typename, a typedef name or a template name. It can't be a function name. It can really only be a macro, which are the only remaining named entities. For that, see the "Yes (well, sort of)" answer.正如其他人指出的那样,遗憾的是您无法编写自定义运算符,但使用宏您可以获得类似的行为。实际上,使用 C 风格的转换非常简单,请参见下文。
这里
4 to 5
将返回一个To_Range类型的对象。 (Slicing_To_End) 将 5 转换为 Slicing_To_End。现在编译器想要找到一个合适的 == 运算符。唯一的一个是我们的自定义运算符,它将第一个位置和第二个 Slicing_To_End 中的整数作为输入,并返回我们的类型 To_Range。当然,您也可以返回其他类型,例如 int、float。As others have pointed out you sadly can not write custom operators but with macros you can get similar behaviour. It is actually really easy with c style casting see below.
Here
4 to 5
will give back an object of type To_Range. (Slicing_To_End) casts 5 to Slicing_To_End. Now the compiler wants to find an == operator that fits. The only one is our custom operator that takes as input an integer on the first position and in the second Slicing_To_End and returns our type To_Range. You also could return of course other types like int,float.您的建议只不过是语法糖 for:
并且事实上 cstring 和 std::string 中已经有一个函数可以做到这一点。这可能有点像回答“这是个好主意吗?”但也不完全是;而是问“为什么你需要/想要?”
Your suggestion would be nothing more than syntactic sugar for:
and in fact there are already a functions to do that in both cstring and std::string. Which is perhaps a bit like answering "is it a good idea?" but not quite; rather asking "why would you need/want to?"