如何使用Boost MPL在一个函数中具有多个返回点
How to use Boost MPL to have several return points in a function?
考虑以下代码:
struct Param {};
struct Base {
virtual char f(Param const &) const = 0;
};
struct A : Base {
explicit A(Param const &) {}
virtual char f(Param const &) const {return 'A';}
};
struct B : Base {
explicit B(Param const &) {}
virtual char f(Param const &) const {return 'B';}
};
struct C : Base {
explicit C(Param const &) {}
virtual char f(Param const &) const {return 'C';}
};
char my_function(Param const & param, Base const & base)
{
if(A const * const p = dynamic_cast<A const *>(&base)) {
return p->f(param);
}
if(B const * const p = dynamic_cast<B const *>(&base)) {
return p->f(param);
}
if(C const * const p = dynamic_cast<C const *>(&base)) {
return p->f(param);
}
return '0';
}
然后如果我写
Param x, y;
std::cout << my_function(x, B(y)) << std::endl;
它输出CCD_ 1。
我的目标是更改my_function
的实现,使其能够支持在编译时定义的Base
的一组子类型。在这里,我手工编写了我将获得的类型集合{A, B, C}
的扩展代码。我想用一组类型来模板化my_function
,并这样称呼它:
std::cout << my_function<boost::mpl::set<A, B, C> >(x, B(y)) << std::endl;
输出B
,或者,例如:
std::cout << my_function<boost::mpl::set<A, C> >(x, B(y)) << std::endl;
输出CCD_ 7。
我不知道该使用哪个MPL构造来实现这个结果。
我最初认为调用find_if
可以找到集合中可以动态广播base
的第一个类型,但事实上,与大多数MPL算法一样,该算法静态地生成结果,因此显然不能与运行时参数(B
0)一起使用。
唯一被归类为"运行时"的MPL算法是for_each
,但我不知道如何使用它来产生与我的多个返回语句相同的效果(我甚至不知道这是否可能)。感谢任何能帮助我的MPL演讲者。
附言:不要告诉我我应该避免动态投射,否则我可以简单地使用
char my_function(Param const & param, Base const & base) {return base.f(param);}
与现实生活中的问题相比,我已经简化了代码示例,并且无法更改现有的设计。
这样的东西应该可以工作:
struct functor
{
public:
functor(Param const & param, Base const & base)
: param_(param),
base_(base),
found_(false)
{
}
template<typename Child>
void operator()(Child*)
{
if (!found_)
{
if(Child const * const p = dynamic_cast<Child const *>(&base_))
{
value_ = p->f(param_);
found_ = true;
}
}
}
char get_value()
{
return value_;
}
private:
Param const & param_;
Base const & base_;
bool found_;
char value_;
};
template <typename ...Types>
char my_function(Param const & param, Base const & base)
{
typedef boost::mpl::vector<Types...>::type children;
functor f(param, base);
boost::mpl::for_each<children>(std::ref(f));
return f.get_value();
}
int main()
{
Param x, y;
std::cout << my_function<A*, B*, C*>(x, B(y)) << std::endl;
return 0;
}
这是我找到的解决方案。
namespace detail {
template <typename First, typename Last>
struct my_function_impl {
static char apply(Param const & param, Base const & base)
{
BOOST_MPL_ASSERT_NOT((boost::is_same<First, Last>));
typedef typename boost::mpl::deref<First>::type Child;
BOOST_MPL_ASSERT((boost::is_base_of<Base, Child>));
if(Child const * const p = dynamic_cast<Child const *>(&base)) {
return p->f(param);
}
typedef typename boost::mpl::next<First>::type Next;
return my_function_impl<Next, Last>::apply(param, base);
}
};
template <typename It>
struct my_function_impl<It, It> {
static char apply(Param const &, Base const &)
{
return '0';
}
};
} // namespace detail
template <typename ContainerOfTypes>
char my_function(Param const & param, Base const & base)
{
typedef typename boost::mpl::begin<ContainerOfTypes>::type Begin;
typedef typename boost::mpl::end<ContainerOfTypes>::type End;
return detail::my_function_impl<Begin, End>::apply(param, base);
}
电话:
std::cout << my_function<boost::mpl::set<A, B, so::Base> >(x, C(y)) << std::endl;
欢迎提出任何简化或改进建议。
相关文章:
- 从函数返回const char*数组
- 检查函数返回类型是否与STL容器类型值相同
- 从 c 或 cpp 系列子函数返回到主函数
- 从函数返回任意简单类型的数据
- 警告:在函数返回类型 [-Wignore 限定符] 时忽略类型限定符
- 从 C++ 中的函数返回数组地址问题
- VirtDisk.h QueryChangesVirtualDisk() 函数返回 RangeCount 为 0
- 为什么glGetSubroutineIndex为不同的函数返回相同的值?
- 在 c++ 中将函数返回类型指定为模板参数
- 从封装在对象中的函数 C++ 返回时为空的列表
- 为什么向量内部的指针在从函数返回时会发生变化?
- 函数返回的 rvalue 引用(表达式)是 xvalue - 但没有标识?
- 程序中的布尔函数返回输入的范围无论如何都是无效的
- 寿命延长从函数返回引用
- 程序不向函数返回值
- 字符串函数返回奇怪的值
- 类的大问题,以及从空函数c++返回
- 为什么在尝试测量函数返回所需的时间时,我的运行时编号是错误的?
- C++二叉搜索树模板从函数返回节点
- NVCC 错误:string_view.h:constexpr 函数返回是非常量