On 10 Mai, 05:26, Krzysztof Czainski <1czaj...@[EMAIL PROTECTED]
> wrote:
> On May 9, 5:15 pm, Daniel Krügler <daniel.krueg...@[EMAIL PROTECTED]
>
> wrote:
> > An interesting enhancement proposal for Cloneable could be to
> > add one further template parameter as smart-pointer policy
> > Yes, this is fine. And by means of the virtual inheritance you
> > simulate what other languages usually call "interface" (but
> > you know that). And if you use Cloneable<D, boost::shared_ptr<D> >
> > this will match the style of those languages even more ;-)
>
> Yes, exactly ;-)
>
> Here's the enhancement You proposed with another little enhancement of
> my own:
>
> [code]
> template < typename Derived, typename DefaultPtrPolicy =
> std::auto_ptr<Derived> >
> class Cloneable : public virtual CloneableBase
> {
> public:
>
> BOOST_STATIC_ASSERT(( boost::is_base_of< Derived, typename
> DefaultPtrPolicy::element_type >::value ));
>
> typedef DefaultPtrPolicy SmartPtr;
>
> SmartPtr clone() const { return clone<SmartPtr>(); }
>
> template < typename OtherPtrPolicy >
> OtherPtrPolicy clone() const
> {
> BOOST_STATIC_ASSERT(( boost::is_base_of< Derived, typename
> OtherPtrPolicy::element_type >::value ));
> // note: must be dynamic_cast due to virtual inheritance of
> CloneableBase
> Derived* p = dynamic_cast<Derived*>( doClone() );
> BOOST_ASSERT( p != NULL );
> return OtherPtrPolicy( p );
> }
>
> // note: the below would break compatibility with NaturallyCloneable
> //protected:
> // Cloneable* doClone() const = 0;};
>
> [/code]
>
> Still, one thing bothers me.. The static assertion "is_base_of" should
> stay, but it would be nice to also be able to use a normal Derived*
> instead of some smart ptr type. Can that be achieved simply?
>
> class X : public Cloneable<X,X*>, NaturallyCloneable<X> {};
Hmmh, didn't you mean
class X : public Cloneable<X,X*>, public NaturallyCloneable<X> {};
instead?
This is not so hard to solve given Boost's type-traits.
In the following code I also replaced the inner
BOOST_STATIC_ASSERT of the clone template by a SFINAE
technique and I allowed for cv-qualified return types:
#include <memory>
#include <boost/static_assert.hpp>
#include <boost/assert.hpp>
#include <boost/cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/if.hpp>
template<typename T>
struct RemoveElementType {
typedef typename T::element_type type;
};
template<typename Target, typename PtrPolicy>
struct MatchingPtrs : boost::integral_constant<bool,
boost::is_base_of<Target, typename boost::remove_cv<
typename boost::mpl::if_<
boost::is_pointer<PtrPolicy>,
boost::remove_pointer<PtrPolicy>,
RemoveElementType<PtrPolicy>
>::type::type>::type>::value> {
};
template < typename Derived, typename DefaultPtrPolicy =
std::auto_ptr<Derived> >
class Cloneable : public virtual CloneableBase
{
public:
BOOST_STATIC_ASSERT(( MatchingPtrs<Derived,
DefaultPtrPolicy>::value ));
typedef DefaultPtrPolicy SmartPtr;
SmartPtr clone() const { return clone<SmartPtr>(); }
template < typename OtherPtrPolicy >
typename boost::enable_if<MatchingPtrs<Derived, OtherPtrPolicy>,
OtherPtrPolicy>::type clone() const
{
// note: must be dynamic_cast due to virtual inheritance of
CloneableBase
Derived* p = dynamic_cast<Derived*>( doClone() );
BOOST_ASSERT( p != NULL );
return OtherPtrPolicy( p );
}
};
class A : public Cloneable<A> {}; // abstract base for B and C
class B : public A, public NaturallyCloneable<B> {};
class C : public A { virtual A* doClone() const { return new C; } };
class X : public Cloneable<X,X*>, public NaturallyCloneable<X> {};
int main()
{
B b;
C c;
X x;
b.clone();
c.clone();
b.clone< boost::shared_ptr<A> >(); // see code below
c.clone< boost::shared_ptr<A> >();
c.clone< boost::shared_ptr<const volatile A> >();
b.clone< A* >();
c.clone< const A* >();
x.clone();
x.clone< boost::shared_ptr<X> >();
x.clone< X* >();
}
HTH & Greetings from Bremen,
Daniel Krügler
--
[ See http://www.gotw.ca/resources/clcm.htm
for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


|