Use C++0x rvalue references in Object, Handle_for, MP_Float and Quotient.

This commit is contained in:
Sylvain Pion 2008-08-27 14:19:18 +00:00
parent 6c9be1ff58
commit 8865f7ea4f
6 changed files with 181 additions and 44 deletions

View File

@ -206,6 +206,18 @@ public:
MP_Float(long double d);
#ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
MP_Float(MP_Float && m)
: v(std::move(m.v)), exp(m.exp) {}
MP_Float& operator=(MP_Float && m)
{
clear();
swap(m);
return *this;
}
#endif
MP_Float operator+() const {
return *this;
}
@ -252,6 +264,12 @@ public:
return NEGATIVE;
}
void clear()
{
v.clear();
exp = 0;
}
void swap(MP_Float &m)
{
std::swap(v, m.v);

View File

@ -96,10 +96,60 @@ class Quotient
template <class T>
Quotient(const Quotient<T>& n) : num(n.numerator()), den(n.denominator()) {}
Quotient& operator=(const NT & n)
{
num = n;
den = 1;
return *this;
}
Quotient& operator=(const CGAL_double(NT) & n)
{
num = n;
den = 1;
return *this;
}
Quotient& operator=(const CGAL_int(NT) & n)
{
num = n;
den = 1;
return *this;
}
#ifdef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
template <class T1, class T2>
Quotient(const T1& n, const T2& d) : num(n), den(d)
{ CGAL_precondition( d != 0 ); }
#else
template <class T1, class T2>
Quotient(T1 && n, T2 && d)
: num(std::forward<T1>(n)), den(std::forward<T2>(d))
{ CGAL_postcondition( den != 0 ); }
Quotient(Quotient && q)
: num(std::move(q.num)), den(std::move(q.den)) {}
Quotient(NT && n)
: num(std::move(n)), den(1) {}
Quotient& operator=(NT && n)
{
num = std::move(n);
den = 1;
return *this;
}
Quotient& operator=(Quotient && q)
{
num = std::move(q.num);
den = std::move(q.den);
return *this;
}
#endif
Quotient<NT>& operator+= (const Quotient<NT>& r);
Quotient<NT>& operator-= (const Quotient<NT>& r);
Quotient<NT>& operator*= (const Quotient<NT>& r);

View File

@ -37,7 +37,7 @@ Objects of type \ccRefName\ are normally created using the global function
\ccMethod{Object &operator=(const Object &o);}
{Assignment.}
\ccMethod{bool is_empty();}{returns true, if \ccVar\ does not
\ccMethod{bool empty();}{returns true, if \ccVar\ does not
contain an object.}
\ccMethod{const std::type_info & type() const;}

View File

@ -55,18 +55,6 @@ public:
ptr_->count = 1;
}
Handle_for(const Handle_for& h)
: ptr_(h.ptr_)
{
++(ptr_->count);
}
// TODO :
// We should also think about providing template constructors in
// order to forward the functionality of T to Handle_for<T> without
// the need to an intermediate copy.
// Currently it's not working, because some places use conversions.
Handle_for(const T& t)
: ptr_(allocator.allocate(1))
{
@ -74,6 +62,15 @@ public:
ptr_->count = 1;
}
#ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
Handle_for(T && t)
: ptr_(allocator.allocate(1))
{
new (&(ptr_->t)) T(std::move(t));
ptr_->count = 1;
}
#endif
/* I comment this one for now, since it's preventing the automatic conversions
to take place. We'll see if it's a problem later.
template < typename T1 >
@ -85,6 +82,15 @@ public:
}
*/
#if !defined CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES && !defined CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
template < typename T1, typename T2, typename... Args >
Handle_for(T1 && t1, T2 && t2, Args && ... args)
: ptr_(allocator.allocate(1))
{
new (&(ptr_->t)) T(std::forward<T1>(t1), std::forward<T2>(t2), std::forward<Args>(args)...);
ptr_->count = 1;
}
#else
template < typename T1, typename T2 >
Handle_for(const T1& t1, const T2& t2)
: ptr_(allocator.allocate(1))
@ -108,15 +114,12 @@ public:
new (&(ptr_->t)) T(t1, t2, t3, t4);
ptr_->count = 1;
}
#endif // CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES
~Handle_for()
Handle_for(const Handle_for& h)
: ptr_(h.ptr_)
{
if (! is_shared() ) {
allocator.destroy( ptr_);
allocator.deallocate( ptr_, 1);
}
else
--(ptr_->count);
++(ptr_->count);
}
Handle_for&
@ -138,6 +141,39 @@ public:
return *this;
}
#ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
// Note : I don't see a way to make a useful move constructor, apart
// from e.g. using NULL as a ptr value, but this is drastic.
Handle_for&
operator=(Handle_for && h)
{
swap(h);
return *this;
}
Handle_for&
operator=(T && t)
{
if (is_shared())
*this = Handle_for(std::move(t));
else
ptr_->t = std::move(t);
return *this;
}
#endif
~Handle_for()
{
if (! is_shared() ) {
allocator.destroy( ptr_);
allocator.deallocate( ptr_, 1);
}
else
--(ptr_->count);
}
void
initialize_with(const T& t)
{

View File

@ -99,6 +99,15 @@ class Handle_for_virtual
return *this;
}
#ifndef CGAL_CFP_NO_CPP0X_RVALUE_REFERENCE
Handle_for_virtual&
operator=( Handle_for_virtual && h)
{
swap(h);
return *this;
}
#endif
// protected:
typedef RefCounted element_type;
@ -117,6 +126,10 @@ class Handle_for_virtual
id() const
{ return reinterpret_cast<long int>(&*ptr); }
void
swap(Handle_for_virtual & h)
{ std::swap(h.ptr, ptr); }
const RefCounted *
Ptr() const
{ return ptr; }
@ -158,8 +171,6 @@ protected:
}
*/
private:
RefCounted * ptr;
};

View File

@ -38,15 +38,19 @@ CGAL_BEGIN_NAMESPACE
template <class T>
class Wrapper : public Ref_counted_virtual
{
Wrapper(const Wrapper&); // deleted to make sure we don't make useless copies
public:
Wrapper(const T& object) : _object(object) {}
Wrapper() {}
operator T() const { return _object; }
#ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
Wrapper(T && object) : _object(std::move(object)) {}
#endif
~Wrapper() {}
const T& get() const { return _object; }
virtual const std::type_info & type() const
{
return typeid(T);
@ -64,7 +68,7 @@ class Wrapper : public Ref_counted_virtual
class Object
: public Handle_for_virtual<Ref_counted_virtual>
{
struct empty {};
struct Empty {};
typedef Handle_for_virtual<Ref_counted_virtual> base;
public:
@ -73,14 +77,25 @@ class Object
Object()
{
initialize_with(Wrapper<empty>());
typedef Wrapper<Empty> Wrap;
ptr = new Wrap(Empty());
}
#ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
template <class T>
Object(T && t, private_tag)
{
typedef Wrapper< typename std::remove_reference< typename std::remove_cv<T>::type >::type > Wrap;
ptr = new Wrap(std::forward<T>(t));
}
#else
template <class T>
Object(const T&t, private_tag)
{
initialize_with(Wrapper<T>(t));
typedef Wrapper<T> Wrap;
ptr = new Wrap(t);
}
#endif
template <class T>
bool assign(T &t) const
@ -91,31 +106,48 @@ class Object
const Wrapper<T> *wp = dynamic_cast<const Wrapper<T> *>(Ptr());
if (wp == NULL)
return false;
t = *wp;
t = wp->get();
#ifdef _MSC_VER
}
catch (...) {
CGAL_error_msg( "Your compiler must support RTTI");
CGAL_error_msg("Your compiler must support Run-Time Type Information (RTTI)");
}
#endif
return true;
}
bool
empty() const
{
Empty E;
return assign(E);
}
// is_empty() is kept for backward compatibility.
// empty() was introduced for consistency with e.g. std::vector::empty().
bool
is_empty() const
{
empty E;
return assign(E);
return empty();
}
const std::type_info & type() const
{
return is_empty() ? typeid(void) : Ptr()->type();
return empty() ? typeid(void) : Ptr()->type();
}
};
#ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE
template <class T>
inline
Object
make_object(T && t)
{
return Object(std::forward<T>(t), Object::private_tag());
}
#else
template <class T>
inline
Object
@ -123,6 +155,7 @@ make_object(const T& t)
{
return Object(t, Object::private_tag());
}
#endif
template <class T>
inline
@ -143,14 +176,6 @@ struct Bad_object_cast
}
};
/*
template <class T>
inline
T * object_cast(Object * o)
{
return o && o->type() == typeid(T) ? o->object_ptr() : NULL;
}
*/
template <class T>
inline
@ -160,9 +185,6 @@ const T * object_cast(const Object * o)
if (wp == NULL)
return NULL;
return static_cast<const T*>(wp->object_ptr());
// return o && o->type() == typeid(T)
// ? static_cast<const T*>(o->object_ptr())
// : NULL;
}
template <class T>