use*_*508 7 c++ boost boost-variant
我希望从boost变量中获取指向基类的指针,如果我将orignally指针放到派生类上.有没有办法实现这一点.以下代码不起作用.
class A{ public: virtual ~A(){}}; class B : public A{};
typedef boost::variant<A*,B*> MyVar;
MyVar var = new B;
A* a = boost::get<A*> (var); // the following line throws exception
Run Code Online (Sandbox Code Playgroud)
也许有人有想法怎么写我自己的get函数如果请求的类型是基类的存储类型的变种,这将考验,然后做相应的投
Pio*_*cki 10
您可以使用operator()以下模板编写自己的访问者:
#include <iostream>
#include <boost/variant.hpp>
#include <type_traits>
struct A { virtual ~A() {} virtual void foo() {} };
struct B : A { virtual void foo() { std::cout << "B::foo()" << std::endl; } };
template <typename T>
struct visitor : boost::static_visitor<T>
{
private:
using Base = typename std::remove_pointer<
typename std::remove_cv<
typename std::remove_reference<T>::type
>::type
>::type;
template <typename U>
T get(U& u, std::true_type) const
{
return u;
}
template <typename U>
T get(U& u, std::false_type) const
{
throw boost::bad_get{};
}
public:
template <typename U>
T operator()(U& u) const
{
using Derived = typename std::remove_pointer<
typename std::remove_cv<
typename std::remove_reference<U>::type
>::type
>::type;
using tag = std::integral_constant<bool
, (std::is_base_of<Base, Derived>::value
|| std::is_same<Base, Derived>::value)
&& std::is_convertible<U, T>::value>;
return get(u, tag{});
}
};
template <typename T, typename... Args>
T my_get(boost::variant<Args...>& var)
{
return boost::apply_visitor(visitor<T>{}, var);
}
int main()
{
boost::variant<A*,B*> var = new B;
A* a = my_get<A*>(var); // works!
a->foo();
B* b = my_get<B*>(var); // works!
b->foo();
}
Run Code Online (Sandbox Code Playgroud)
输出:
B::foo()
B::foo()
Run Code Online (Sandbox Code Playgroud)
问答部分:
这个解决方案很奇怪!
不它不是.这正是Boost.Variant中访问者类的用途.类似的解决方案已经存在于最新版本的Boost.Variant中boost::polymorphic_get<T>.可悲的是,它是为其他目的而设计的,不能在这里使用.
您好,谢谢大家的回答和评论,我得出以下结论,它在编译时决定类型是否相互继承。它似乎有效,而且对我来说似乎更容易理解。
#include <iostream>
#include <boost/variant.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility.hpp>
using namespace boost::type_traits;
struct A { virtual ~A() {} virtual void foo() {} };
struct B : A { virtual void foo() { std::cout << "B::foo()" << std::endl; } };
typedef boost::variant<B*,A*,C*> MyVar;
template <typename A,typename B>
struct types_are_inheritance_related
{
static const bool value=
ice_or<
boost::is_base_of<A, B>::value,
boost::is_base_of<B, A>::value
>::value;
};
template<class Base>
class get_visitor
: public boost::static_visitor<Base*> { public:
template<class T>
Base* operator()( T* t, typename boost::enable_if<types_are_inheritance_related<Base,T> >::type* dummy = 0)
{
Base* b = dynamic_cast<Base*> ( t);
return b;
}
template<class T>
Base* operator()( T* t, typename boost::disable_if<types_are_inheritance_related<Base,T> >::type* dummy = 0)
{
return 0;
}
};
template<class T>
T* get_var_value(MyVar& var)
{
get_visitor<T> visitor;
T* aa= var.apply_visitor(visitor);
return aa;
}
int main()
{
MyVar var = new B;
A* a = get_var_value<A*>(var); // works!
a->foo();
B* b = get_var_value<B*>(var); // works!
b->foo();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1834 次 |
| 最近记录: |