一直以来,我发现自己都在做这样的事情:
Animal *animal = ...
if (Cat *cat = dynamic_cast<Cat *>(animal)) {
...
}
else if (Dog *dog = dynamic_cast<Dog *>(animal)) {
...
}
else { assert(false); }
当我在C++11中看到闭包时,我想知道,像这样的东西是可能的吗?
Animal *animal = ...
typecase(animal,
[](Cat *cat) {
...
},
[](Dog *dog) {
...
});
实现typecase应该很容易,但我一直遇到一个问题,它不能弄清楚函数的参数,所以它不知道尝试dynamic_cast到什么,因为很难推导出lambdas的参数.花了几天时间搜索谷歌和SO,但最终找到了,所以我会在下面分享我的答案.
6条答案
按热度按时间fykwrbwg1#
多亏了ecatmur在https://stackoverflow.com/a/13359520的回答,我才能从lambda中提取签名。完整的解决方案如下所示:
下面是一个用法示例:
如果谁有什么改进,请告诉我!
b0zn9rqh2#
实施
用法
我现在还没有C11编译器来尝试这个方法,但我希望这个想法是有用的。根据编译器的类型推断能力,你可能需要也可能不需要两次指定case的类型--我对C11-pro的了解还不够,看一看就知道了。
js4nwp543#
前一段时间,我正在尝试编写一个库来完成这一任务。
你可以在这里找到它:
https://github.com/nicola-gigante/typeswitch
这个项目是相当雄心勃勃的,有很多计划中的特性,它仍然需要完成(还有一个重要的bug,我已经知道了,但是我在这几个月里没有时间再处理它了)。然而,对于您的经典类层次结构的用例,它将完美地工作(我认为)。
基本机制与您之前发布的相同,但我尝试用更多的特性来扩展这个概念:
T
是所有子句返回的类型的公共类型。如果没有默认大小写,则返回类型为optional<T>
而不是T
。boost::optional
或 * Library Foundentals TS * 当前草案中std::experimental::optional
的任何实现(例如,libc++
提供了一个)。boost::any
对象中包含的类型。dynamic_cast
,这在使用提供了自己的强制转换基础设施的库时很有用,比如Qt的qobject_cast
,或者在你自己的标记联合体上实现类型开关时也很有用。这个库已经完成了,除了
README
中记录的一个bug,这个bug使得不可能将非多态类型与静态重载解决规则相匹配,但是这种情况只在模板化的泛型代码中有用,并且不涉及像您这样的大多数用例。不过我想把它寄到这里总比不使用好。mfpqipee4#
我认为这取决于你想在编译时还是运行时做这件事。对于编译时,Verdagon的答案更好,在运行时你可以这样做
但这两种方法都是错误的
virtual
关键字是针对这一点的,您必须像Arie所说的那样做,否则您的体系结构中存在错误syqv5f0l5#
我认为您实际上希望使用继承,而不是类型大小写(我以前从未见过,非常简洁:)或类型检查。
小例子:
在本例中,我想打印动物特有的声音而不进行特定的类型检查,为此,我使用了Animal的每个子类所具有的虚函数"makeSound"和重写来打印该动物的正确输出。
希望这是你想要的。
q5iwbnjs6#
一个小技巧,如何创建关于类型的静态信息,以便可以用一个开关静态或动态地快速比较它们。