gpt4 book ai didi

c++ - 将对象转换为其基数的子集

转载 作者:行者123 更新时间:2023-11-30 05:25:24 25 4
gpt4 key购买 nike

我有一个定义如下的类:

template< typename... >
class Base;

template< typename T >
class Base<T>{
//pure virtual functions dependent on T
public:
virtual ~Base() = default;
};

template< typename... Ts >
class Base<Ts...>
: public Base<Ts>...
{
//empty
};

问题是:

  • 有没有办法投Base< T1, T2, T3 >&Base< T2, T3 >&
  • 有没有办法投Base< T1, T2, T3 >&Base< T2, T1, T3 >&

编辑:让我在没有模板的情况下改写这个问题。我有一个定义如下的类:

class Base_int{
public:
virtual int f() = 0;
virtual ~Base_int() = default;
};
class Base_float{
public:
virtual float f() = 0;
virtual ~Base_float() = default;
};
class Base_double{
public:
virtual double f() = 0;
virtual ~Base_double() = default;
};

class IFD
: public Base_int
, public Base_float
, public Base_double
{ };

class IF
: public Base_int
, public Base_float
{ };

class FID
: public Base_float
, public Base_int
, public Base_double
{ };

问题是:

  • 有没有办法投IFD&IF&
  • 有没有办法投IFD&FID&

编辑 2:进一步澄清:我正在实现一个通用的访问者模式实现,我将在一个通用的树容器中使用它。我正在使用混合 (CRTP) 模式来实现 accept访问类的方法以及visit来访者的方法。这些方法是虚拟的,我需要我在 OP 中发布的层次结构。有一个名为 IVisitor<Ts...> 的基类实现访问者的接口(interface) Ts... .该接口(interface)由类组成 IVisitor<T> - 就像在 OP 中一样。实现 IVisitor<Ts...> 的具体访问者定义如下:

class ConcreteVisitor : public IVisitor<T1, T2, T2, ...>{
//Implementation of the visit methods defined in IVisitor<Ts...>
virtual void visit( T1& v ) override { /*...*/ }
virtual void visit( T2& v ) override { /*...*/ }
virtual void visit( T3& v ) override { /*...*/ }
}

我突然想到,如果 ConcreteVisitor 可以访问 IVisitor<Us...> 中的内容,那将会很有用。其中 Us...Ts... 的子集或排列.为了做到这一点,我需要将它转换到那个基地 - 因此就是这个问题。

最佳答案

在进一步检查问题之后,我意识到我需要一个包装器来使通用访问者适应我的界面。这是我使用的解决方案 - 请参阅 IVisitable::adaptVisitor 静态方法:

#include <iostream>
#include <typeinfo>
#include <vector>

//Visitable base class
template< typename >
class Visitable;

//Visitable class interface
template< typename... >
class IVisitor;

//Assures that the visitor type derives from IVisitor
template< typename IVisitor_type >
class IVisitable
: public IVisitable<typename IVisitor_type::derives_from_IVisitor>
{ };

//Implements the Visitor adapter
template< typename Derived, typename Root, typename... Ts >
class VisitorWrapper;

//IVisitable base class
template< typename... Ts >
class IVisitable< IVisitor<Ts...> >{
public:
//Visitor interface type
using IVisitor = IVisitor<Ts...>;

//Visitor adapter type
template< typename F >
class VisitorAdapter;

//Helper function
template< typename F >
static VisitorAdapter<F&&> adaptVisitor( F&& f )
{ return { std::forward<F>(f) }; }

//Accept visitor pure virtual methods
virtual void accept( IVisitor& ) = 0;
virtual void accept( IVisitor& ) const = 0;
virtual void accept( IVisitor&& ) = 0;
virtual void accept( IVisitor&& ) const = 0;

protected:
virtual ~IVisitable() = default;
};

//Implements the visitor adapter of F class
template< typename... Ts >
template< typename F >
class IVisitable<IVisitor<Ts...>>::VisitorAdapter
: public VisitorWrapper< VisitorAdapter<F>, ::IVisitor<Ts...>, Ts... >
//Derives from VisitorWrapper that implements all of the virtual methods
{
public:
template< typename U >
void visit( U&& u ){ f( std::forward<U>(u) ); }

VisitorAdapter( F f_ ) : f(f_) { }

F f;
};

//Basic IVisitor of T
template< typename T >
class IVisitor<T>{
public:
using derives_from_IVisitor = IVisitor;

virtual void visit( T& ) = 0;
virtual void visit( const T& ) = 0;

virtual ~IVisitor() = default;
};

//IVisitor of Ts derives from Visitor<T>
template< typename T, typename... Ts >
struct IVisitor<T, Ts...>
: IVisitor<T>, IVisitor<Ts...>
{
using derives_from_IVisitor = IVisitor;
};

//Visitable base class. Final to prevent errors
template< typename Derived >
struct Visitable final
{
//Extends class wraps the Base class inheritance
template< typename Base >
class extends : public Base
{
public:
//Propagate the IVisitor interface.
using IVisitor = typename Base::IVisitor;

//Prevents incomprehensible errors when visitor doesn't
//define Derived as its visited class
static_assert(
std::is_base_of<::IVisitor<Derived>, IVisitor>::value
, "Base class visitor interface does not support visitation of this type"
);

//Implement accept method via CRTP
virtual void accept( IVisitor& v ) override{
static_cast< ::IVisitor<Derived>& >(v).visit( // Disambiguation
static_cast<Derived&>(*this) // CRTP
);
}
virtual void accept( IVisitor& v ) const override {
static_cast< ::IVisitor<Derived>& >(v).visit( // Disambiguation
static_cast<const Derived&>(*this) // CRTP
);
}
virtual void accept( IVisitor&& v ) override{
static_cast< ::IVisitor<Derived>&& >(v).visit( // Disambiguation
static_cast<Derived&>(*this) // CRTP
);
}

virtual void accept( IVisitor&& v ) const override{
static_cast< ::IVisitor<Derived>&& >(v).visit( // Disambiguation
static_cast<const Derived&>(*this) // CRTP
);
}
protected:
virtual ~extends() = default;
};

~Visitable() = delete;
};

template< typename > struct print_type;

//Uses CRTP to implement visit method of IVisitor
//Consumes the list of Ts... so that the inheritance hierarchy is linear
template<
typename Derived // CRTP
, typename... Rs // Base class (IVisitor<Rs...>)
, typename T // Currently implemented type
, typename... Ts // The rest of types
> class VisitorWrapper< Derived, IVisitor<Rs...>, T, Ts... >
: public VisitorWrapper< Derived, IVisitor<Rs...>, Ts... > //Consume T
{
//Cast to Derived and call visit method
virtual void visit( T& v ){ static_cast<Derived*>(this)->visit(v); }
virtual void visit( const T& v ){ static_cast<Derived*>(this)->visit(v); }
};

//Uses CRTP to implement visit method of IVisitor
template< typename Derived, typename... Rs, typename T >
class VisitorWrapper< Derived, IVisitor<Rs...>, T >
: public IVisitor<Rs...> //IVisitor<Ts...>
{
virtual void visit( T& v ){ static_cast<Derived*>(this)->visit(v); }
virtual void visit( const T& v ){ static_cast<Derived*>(this)->visit(v); }
};

/////////////////////////////////////////////////////

class ABCVisitor
: public IVisitor< class A, class B, class C >
{ };

class ABC : public IVisitable< ABCVisitor >
{};

class A : public Visitable<A>::extends<ABC> {};
class B : public Visitable<B>::extends<ABC> {};
class C : public Visitable<C>::extends<B> {};

int main()
{
auto p = [](const auto& v){ std::cout << typeid(v).name() << std::endl; };
auto printer = ABC::adaptVisitor( p );
A a; B b; C c;
std::vector< ABC* > vs{ &a, &b, &c };
for( const auto& v : vs )
v->accept(printer);
return 0;
}

关于c++ - 将对象转换为其基数的子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38270622/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com