Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
class Flying { /* ... */ };
class Quacking { /* ... */ };
class FlyingAndQuacking : public Flying, public Quacking { /* ... */ };
class ReadheadDuck : public FlyingAndQuacking { /* ... */ };
class RubberDuck : public Quacking { /* ... */ };
class A {};
class B {};
class C {};
class Somebody : public A, public B, piblic C {};
class AC : public A, public C {}
void methodAC(AC * one)
{
}
int main()
{
Somebody * smb = new Somebody();
methodAC(smb); <u>// Ошибка компиляции ...</u>
}void methodAB( {A*,B*} one );void methodAB( {A,B} * one );<T extends Quackable & Duck> void doFlyQuacking(T one)
{
// ...
}
template< class T >
void doFlyQuacking( T *p )
{
static_assert( std::is_base_of< IQuackable, T >::value );
static_assert( std::is_base_of< IFlyable, T >::value );
}
static_assert( !std::is_base_of<T, IQuackable>::value );static_assert( std::is_base_of<IQuackable, T>::value );#include <boost/concept_check.hpp>
#include <boost/concept/requires.hpp>
template <class T>
BOOST_CONCEPT_REQUIRES(
((boost::Convertible<T, Quackable>))
((boost::Convertible<T, Flyable>)),
(void)
) doFlyQuacking(T *one) {
...
}
#include "stdafx.h"
class A{ virtual ~A(){} };
class B{ virtual ~B(){} };
class C{ virtual ~C(){} };
template< class T >
class I : public virtual T{};
template< class T1, class T2 >
class II : public virtual I< T1 >, public virtual I< T2 >{};
template< class T1, class T2, class T3 >
class III : public virtual II< T1, T2 >, public virtual II< T1, T3 >, public virtual II< T2, T3 >{};
class X : public III<A,B,C>{};
class Y : public II<A,B>{};
int _tmain( int, _TCHAR*[] )
{
cout << sizeof( X ) << endl; // 40
cout << sizeof( Y ) << endl; // 20
return 0;
}
// Реализация этого выносится в .cpp а также может быть экспортирована
void DoFlyQuackingImpl( IQuackable *pQuackable, IFlyable *pFlyable )
{
pFlyable->Fly();
pQuackable->Quack();
}
// Реализация этого остается в .h, одна строчка это не сильно много
template< class T >
void DoFlyQuacking( T *p )
{
return DoFlyQuackingImpl( p, p );
};
class NA1 {};
class NA2 {};
class NA3 {};
class NA4 {};
template< class T1 = NA1, class T2 = NA2, class T3 = NA3, class T4 = NA4 >
class IGroup
{
class CTrampoline : public T1, public T2, public T3, public T4 {};
public:
typedef CTrampoline type;
};
class IQuackable { /*...*/ };
class IFlyable { /*...*/ };
class CDuck : public IGroup< IQuackable, IFlyable >::type {};
void DoFlyQuacking( IGroup< IQuackable, IFlyable >::type *p )
{
// ...
}
#include "stdafx.h"
// .... Core ...
#include <iostream>
#include <tchar.h>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/sort.hpp>
#include <boost/mpl/at.hpp>
#include <type_traits>
class NA1 { public: enum{ eTypeID = -1 }; };
class NA2 { public: enum{ eTypeID = -2 }; };
class NA3 { public: enum{ eTypeID = -3 }; };
class NA4 { public: enum{ eTypeID = -4 }; };
// Compares T1 and T2, default implementation really compares T1::eTypeID and T2::eTypeID
template< class T1, class T2 >
class Less
: boost::mpl::less< boost::mpl::long_< T1::eTypeID >, boost::mpl::long_< T2::eTypeID > >
{
static_assert( T1::eTypeID != T2::eTypeID || std::is_same< T1, T2 >::value, "TypeID must be unique!" );
};
template<>
class Less< boost::mpl::_, boost::mpl::_ > {};
template< class T1, class T2, class T3, class T4 >
class CTrampoline : public T1, public T2, public T3, public T4 {};
template< class T1 = NA1, class T2 = NA2, class T3 = NA3, class T4 = NA4 >
class IGroup
{
typedef typename boost::mpl::reverse_sort< boost::mpl::vector< T1, T2, T3, T4 >, Less< boost::mpl::_, boost::mpl::_ > >::type
T;
public:
typedef CTrampoline< typename boost::mpl::at_c< T, 0 >::type,
typename boost::mpl::at_c< T, 1 >::type,
typename boost::mpl::at_c< T, 2 >::type,
typename boost::mpl::at_c< T, 3 >::type >
type;
};
// .... Usage ...
class IQuackable { public: enum{ eTypeID = 0 }; /*...*/ };
class IFlyable { public: enum{ eTypeID = 1 }; /*...*/ };
class CDuck : public IGroup< IQuackable, IFlyable >::type {};
void DoFlyQuacking( IGroup< IFlyable, IQuackable >::type *p )
{
// ...
}
int _tmain( int, _TCHAR*[] )
{
CDuck oDuck;
DoFlyQuacking( &oDuck );
return 0;
}
#include "stdafx.h"
// .... Core ...
#include <iostream>
#include <tchar.h>
#include <boost/mpl/front.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/remove_if.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/utility/enable_if.hpp>
struct NA {};
//! Hierarchy generation core
template< class T1, class T2 >
struct Derive : T1, T2 {};
template< class T1 >
struct Derive< T1, NA > : T1 {};
template< class V, class EnableIf = void >
struct GenerateLinearHierarchy
: boost::mpl::identity< Derive<
typename boost::mpl::front< V >::type,
typename GenerateLinearHierarchy< typename boost::mpl::pop_front< V >::type >::type > >
{
};
template< class V >
struct GenerateLinearHierarchy< V, typename boost::enable_if< boost::mpl::empty< V > >::type >
: boost::mpl::identity< NA >
{
};
//! Transforms interface type to proxy-to-interface type
template< class T >
struct InterfaceToProxyTransformOp : boost::mpl::identity< typename T::CProxy > {};
template<>
struct InterfaceToProxyTransformOp< boost::mpl::_ > {};
//! IGroup implementation, V is MPL array of interfaces.
template< class V >
struct IGroup_Impl
{
private:
typedef typename boost::mpl::transform< V, InterfaceToProxyTransformOp< boost::mpl::_ > >::type
TProxies;
class CPointerImpl : public GenerateLinearHierarchy< TProxies >::type
{
template< class V, class T >
typename boost::disable_if< boost::mpl::empty< V > >::type
Initialize( T *p )
{
static_cast< typename boost::mpl::front< V >::type * >( this )->SetTarget( p );
Initialize< typename boost::mpl::pop_front< V >::type >( p );
}
template< class V, class T >
typename boost::enable_if< boost::mpl::empty< V > >::type
Initialize( T * ){}
public:
template< class T >
CPointerImpl( T *p ){ Initialize< TProxies >( p ); };
};
class CPointer
{
public:
template< class T >
CPointer( T *pGroup ) : m_oImpl( pGroup ) {}
public:
CPointerImpl *operator->() { return &m_oImpl; }
const CPointerImpl *operator->() const { return &m_oImpl; }
const CPointerImpl &operator*() const { return m_oImpl; }
CPointerImpl &operator*() { return m_oImpl; }
protected:
CPointerImpl m_oImpl;
};
public:
typedef CPointer
TPointer;
};
template
<
class T1 = NA, class T2 = NA, class T3 = NA,
class T4 = NA, class T5 = NA, class T6 = NA,
class T7 = NA, class T8 = NA, class T9 = NA
>
struct IGroup
: IGroup_Impl<
typename boost::mpl::remove_if<
boost::mpl::vector< T1, T2, T3, T4, T5, T6, T7, T8, T9 >,
std::is_same< boost::mpl::_, NA > >::type >
{
};
template< class T >
class TProxy
{
public:
TProxy() : m_pTarget( nullptr ) {}
void SetTarget( T *pTarget ){ m_pTarget = pTarget; }
protected:
T *m_pTarget;
};
// .... Usage ...
class IQuackable
{
public:
struct CProxy : TProxy< IQuackable >
{
void Quack(){ m_pTarget->Quack(); }
};
public:
virtual void Quack() = 0;
};
class IFlyable
{
public:
struct CProxy : TProxy< IFlyable >
{
void Fly(){ m_pTarget->Fly(); }
};
public:
virtual void Fly() = 0;
};
class IWalkable
{
public:
struct CProxy : TProxy< IWalkable >
{
void Walk(){ m_pTarget->Walk(); }
};
public:
virtual void Walk() = 0;
};
class CDuck : public IQuackable, public IFlyable, public IWalkable
{
public:
virtual void Quack(){ std::cout << "Quack!" << std::endl; }
virtual void Fly(){ std::cout << "Fly!" << std::endl; }
virtual void Walk(){ std::cout << "Walk!" << std::endl; }
};
void DoFlyQuacking( IGroup< IFlyable, IQuackable >::TPointer p ){ p->Fly(); p->Quack(); }
void DoFlyWalkQuacking( IGroup< IFlyable, IWalkable, IQuackable >::TPointer p ){ p->Fly(); p->Walk(); p->Quack(); }
void DoFly( IGroup< IFlyable >::TPointer p ){ p->Fly(); }
int _tmain( int, _TCHAR*[] )
{
CDuck oDuck;
DoFlyQuacking( &oDuck );
DoFlyWalkQuacking( &oDuck );
DoFly( &oDuck );
return 0;
}
- (void)someMethod:(id <UIAlertViewDelegate, UITableViewDataSource, BaseTVCProtocol>)obj;
Концепт группировки типов в C++