C++ 中的模式匹配风格?
我喜欢 Haskell 风格的模式匹配。
我的 C++ 代码如下:
ObjectPtr ptr;
if(ptr.isType<Foo>()) { // isType returns a bool
Ptr<Foo> p = ptr.convertAs<Foo>(); // convertAs returns a Ptr<Foo>
......
}
if(ptr.isType<Bar>()) {
Ptr<Bar> p = ptr.convertAs<Bar>();
......
}
现在,我可以定义任何宏来简化这个过程吗?我已经思考这个问题有一段时间了,但无法进一步简化。
谢谢!
I love Haskell style pattern matching.
I have my C++ code as follows:
ObjectPtr ptr;
if(ptr.isType<Foo>()) { // isType returns a bool
Ptr<Foo> p = ptr.convertAs<Foo>(); // convertAs returns a Ptr<Foo>
......
}
if(ptr.isType<Bar>()) {
Ptr<Bar> p = ptr.convertAs<Bar>();
......
}
Now, are there any macros I can do define to simplify this? I have been pondering this for a while, but can't simplify it further.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
dynamic_cast
似乎会做你想做的事dynamic_cast
would appear to do what you want然后用 Haskell 编写你的程序。
您要做的是切换类型。如果人们想避免虚拟函数,这是一种常见的做法。现在,后者是 C++ 中的 OO 的基石。如果你想避免它们,为什么要用 C++ 编程呢?
至于为什么这会让人皱眉:想象一下,您的代码中有很多这样的代码
,然后有人来将
Baz
添加到ptr
可能的类型中代表。现在,您正在搜索大型代码库,尝试找到所有切换类型的位置,并尝试找出需要添加Baz
的位置。而且,正如 Murphy 所说,当您完成后,
Foz
也会作为类型添加。 (或者,再想一想,如果墨菲按照他的方式行事,那么它就会在你有机会完全添加Baz
之前就悄悄出现。)Then write your program in Haskell.
What you're trying to do is a switch over a type. That's a common thing people do if they want to avoid virtual functions. Now, the latter are a cornerstone of what OO in C++ is all about. If you want to avoid them, why do you program in C++?
As for why this is frowned upon: Imagine you have a lot of code like this
smeared all over your code and then someone comes and adds
Baz
to the possible types thatptr
might represent. Now you're hunting through a big code base, trying to find all those places where you switched over a type, and trying to find out which ones you need to addBaz
to.And, as Murphy has it, just when your done, there comes along
Foz
to be added as a type, too. (Or, thinking again, if Murphy has his way it creeps in before you had a chance too complete addingBaz
.)尝试使用 RTTI 在 C++ 中模拟模式匹配样式是一个好主意,但它肯定有缺点,因为 Haskell 和标准 ML 样式类型构造函数和 C++ 子类之间存在一些显着差异。 (注意:下面,我使用标准 ML 语法,因为我更习惯它。)
a::b:: c::ds
将列表的前三个元素绑定到a
、b
和c
,其余元素则绑定到a
、b
和c
。列表到ds
)。在 C++ 中,您仍然需要深入研究实际的嵌套结构,除非您或其他人想出了比此处提出的更复杂的宏。'a option
。构造函数NONE
和SOME
不是类型,它们是类型为'a option
和'a ->; 的值。 '一个选项
,分别。在 C++ 中,当您定义Foo
和Bar
等子类来模拟类型构造函数时,您会获得新类型。SOME
这样的构造函数是构造它们所属数据类型的值的一流函数。例如,map SOME
的类型为'a list ->; '选项列表
。在C++中,使用子类来模拟类型构造函数,你没有这种能力。最后,与以更典型的方式使用 C++ 多态性相比,您是否从模拟模式匹配中获得了足够的好处?使用宏使模拟模式匹配稍微更简洁(同时对阅读您代码的其他人进行混淆)是否值得?
Attempting to simulate a pattern matching style in C++ using RTTI is a neat idea, but it's bound to have shortcomings, because there are some significant differences between Haskell and Standard ML style type constructors and C++ subclasses. (Note: below, I use Standard ML syntax because I'm more comfortable with it.)
a::b::c::ds
binds the first three elements of the list toa
,b
, andc
, and the rest of the list tods
). In C++, you'll still have to dig around in the actual nested structures, unless you or someone else comes up with far more complicated macros than have been proposed here.datatype 'a option = NONE | SOME of 'a
defines one new type:'a option
. ConstructorsNONE
andSOME
are not types, they are values with types'a option
and'a -> 'a option
, respectively. In C++, when you define subclasses likeFoo
andBar
to simulate type constructors, you get new types.SOME
are first-class functions that construct values of the datatype to which they belong. For example,map SOME
has the type'a list -> 'a option list
. In C++, using subclasses to simulate type constructors, you don't get this ability.In the end, are you getting enough benefit from simulated pattern matching compared to using C++ polymorphism in a more typical way? Is using macros to make simulated pattern matching slightly more concise (while obfuscating it for everyone else who reads your code) worthwhile?
我们共同创作了一个 C++ 模式匹配库,它允许您非常有效地进行模式匹配和类型分析。该库名为 Mach7,已在 BSD 许可下发布,可在 GitHub 上获取:https://github.com/索洛登4/马赫7。您可以在那里找到视频、海报、幻灯片、论文以及源代码。它目前支持 GCC 4.4+、Clang 3.4+ 和 Visual C++ 2010+。欢迎通过针对其存储库提交 GitHub 问题来询问有关该库的问题。
We co-authored a pattern matching library for C++ that allows you to do pattern matching and type analysis very efficiently. The library, called Mach7, has been released under BSD license and is available on GitHub: https://github.com/solodon4/Mach7. You can find videos, posters, slides, papers as well as the source code there. It currently supports GCC 4.4+, Clang 3.4+ and Visual C++ 2010+. Feel free to ask question's about the library by submitting a GitHub issue against its repository.
我假设您的
Ptr
模板具有 NULL 指针的概念。不过,正如其他人所指出的,切换类型通常表明您在 C++ 中做错了什么。您应该考虑使用虚函数。
I'm assuming that your
Ptr
template has the concept of a NULL pointer.Though, as others have noted, switching on type is usually a sign you're doing something wrong in C++. You ought to consider using virtual functions instead.
我认为这个宏正是您想要的:
用法:
我不会在旨在由其他人阅读的代码中推荐此类内容,但是既然您提到了“宏”这个词...
另外,我也不会'不要假装这与 Haskell/OCaml 风格的模式匹配有任何关系。如果您想要一种具有类似于 C++(嗯,有点)语义和真正模式匹配的语言,请检查 Scala。
A think this macro does precisely what you want:
Usage:
I wouldn't recommend this sort of stuff in code that is meant to be read by somebody else, but since you mentioned the word "macro"...
Also, I wouldn't pretend this has anything to do with pattern matching in the Haskell/OCaml style. Check Scala if you want a language that has semantics similar to C++ (well, sort of) and true pattern matching.