有趣的问题。通常这不会起作用,因为实际上没有办法在运行时用编译时已知的相同语义来表示类型,例如没有虚拟构造函数(查看现代 C++ 设计第 200 页,第 8.2 段)。但是 fusion 支持在编译时对序列for_each
进行迭代并调用运行时函数对象。现在这个函数对象可以是一个通用过滤器,如果它的通用谓词返回 true,则将调用转发到另一个通用函数对象。
现在她是代码:
#include <boost/fusion/container/map.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <string>
#include <iostream>
#include <typeinfo>
using namespace boost::fusion;
template<class Pred,class Fun>
struct filter {
Pred pred_;
Fun& fun_;
filter(Pred p, Fun& f)
: pred_(p)
, fun_(f)
{}
template<class Pair>
void operator()(Pair& pair) const {
if (pred_(pair.second))
fun_(pair);
}
};
template<class Pred,class Fun>
filter<Pred,Fun> make_filter(Pred p, Fun& f) {
return filter<Pred,Fun>(p, f);
}
typedef map
< pair<int, char>
, pair<double, std::string>
> map_type;
struct fun {
template<class First,class Second>
void operator()(pair<First,Second>& t) const {
std::cout
<< typeid(First).name() << std::endl
<< typeid(Second).name() << ":" << t.second << std::endl;
}
};
struct mypred {
template<class T>
bool operator()(T const&) const {
return false;
}
bool operator()(char c) const {
return c=='X';
}
};
int main(int argc, char** argv) {
map_type m(
make_pair<int>('X'),
make_pair<double>("Men")
);
for_each(m, make_filter(mypred(),fun()));
return 0;
}
过滤器类存储一个谓词和一个函数对象。如果谓词pair.second
在您的情况下返回 true,'X'
它会调用函数对象。make_filter
是创建过滤器的小帮手。现在剩下两段 lof 代码:我的非常特殊的 predicate mypred
,它只接受char
(你必须处理更一般的实现的重载)和我的函数对象fun
,它输出类型信息和值。在 mainfor_each
中使用filter
. 请注意:过滤器旨在通过引用获取函数对象,因此它可以传输参数和结果。最后,这是临时访问的一种变体. 如果您关心速度,您应该知道几乎所有内容都可以内联。在此特定示例中,仅比较字符,对于所有其他类型,结果是false
并且不调用任何函数。当然还有很大的改进空间,但我现在没有时间去做。可能有更好的方法来实现这一点,但这是我使用 boost.fusion 的第一个程序:-)。