source code for
Generic<Programming>: Move Constructors by Andrei Alexandrescu
////////////////////////////////////////////////////////////////////////////////
// MOJO: MOving Joint Objects
// Copyright (c) 2002 by Andrei Alexandrescu
//
// Created by Andrei Alexandrescu
//
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author makes no representations about the suitability of this software
// for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
#ifndef MOJOH
#define MOJOH
#include <cassert>
#include <iterator>
#include "TypeManip.h"
namespace mojo
{
template <class T>
class constant // type sugar for constants
{
const T data;
public:
explicit constant(const T& obj) : data(&obj)
{
}
const T& get() const
{
return data_;
}
};
template <class T>
class temporary : private constant<T> // type sugar for temporaries
{
public:
explicit temporary(T& obj) : constant<T>(obj)
{
}
T& get() const
{
return const_cast<T&>(constant<T>::get());
}
};
template <class T>
class fnresult : public T
{
public:
// The cast below is valid given that nobody ever really creates a
// const fnresult object
fnresult(const fnresult& rhs)
: T(temporary<T>(const_cast<fnresult&>(rhs)))
{
}
explicit fnresult(T& rhs) : T(temporary<T>(rhs))
{
}
};
template <class T> struct enabled
{
operator temporary<T>()
{
return temporary<T>(static_cast<T&>(this));
}
operator constant<T>() const
{
return constant<T>(static_cast<const T&>(this));
}
operator fnresult<T>()
{
return fnresult<T>(static_cast<T&>(this));
}
protected:
enabled() {} // intended to be derived from
~enabled() {} // intended to be derived from
};
template <class T>
struct traits
{
enum { enabled = Loki::SuperSubclassStrict< enabled<T>, T >::value };
typedef typename
Loki::Select<
enabled,
temporary<T>,
T&>::Result
temporary;
typedef typename
Loki::Select<
enabled,
fnresult<T>,
T>::Result
fnresult;
};
template <class T>
inline typename traits<T>::temporary as_temporary(T& src)
{
typedef typename traits<T>::temporary temp;
return temp(src);
}
template <class Iter1, class Iter2>
Iter2 move(Iter1 begin, Iter1 end, Iter2 dest)
{
for (; begin != end; ++begin, ++dest)
{
dest = as_temporary(begin);
}
return dest;
}
template <class Iter1, class Iter2>
Iter2 uninitialized_move(Iter1 begin, Iter1 end, Iter2 dest)
{
typedef typename std::iterator_traits<Iter2>::value_type T;
for (; begin != end; ++begin, ++dest)
{
new(dest) T(as_temporary(begin));
}
return dest;
}
}
#endif // MOJOH
————————————————————————————————————————————————————
#include "mojo.h"
#include <iostream>
#include <cassert>
using namespace std;
class Y : public mojo::enabled<Y>
{
public:
Y() // default constructor
{
cout << "CREATING default-constructed object at " << this
<< ‘n’;
}
Y(const Y& rhs) // source is a const value
{
cout << "COPYING const value at " << &rhs
<< " into object at " << this << ‘n’;
}
Y(mojo::fnresult<Y> src) // source is a fnresult
{
Y& rhs = src;
cout << "MOVING mojo::fnresult<Y> at " << &rhs
<< " into object at " << this << ‘n’;
}
Y(mojo::temporary<Y> src) // source is a temporary
{
Y& rhs = src.get();
cout << "MOVING mojo::temporary<Y> at " << &rhs
<< " into object at " << this << ‘n’;
}
~Y()
{
//cout << "DESTROYING object at " << this << ‘n’;
}
};
const Y MakeConstY()
{
return Y();
}
mojo::fnresult<Y> MakeY()
{
//if (cout) return Y();
Y x;
return x;
}
void TakeConstY(const Y&)
{
}
void TakeY(Y&)
{
}
void Discriminate(mojo::temporary<Y>) {}
void Discriminate(mojo::constant<Y>) {}
void Discriminate(Y& obj) { Discriminate(mojo::constant<Y>(obj)); }
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
int main()
{
Y nonConstLValue;
const Y constLValue;
//Y y1(constLValue);
//Y y2(nonConstLValue);
//Y y3(MakeConstY());
Y y4(MakeY());
TakeConstY(Y());
Discriminate(Y()); // calls Discriminate(mojo::temporary<Y>)
Discriminate(MakeY()); // calls Discriminate(mojo::temporary<Y>)
Discriminate(constLValue); // calls Discriminate(mojo::constant<Y>)
Discriminate(nonConstLValue); // calls Discriminate(Y&)
//TakeConstY(MakeY());
//TakeY(Y());
//TakeY(MakeY());
}
——————————————————————————————————————————————————————————
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
// Last update: November 22, 2001
#ifndef TYPEMANIPINC
#define TYPEMANIPINC
namespace Loki
{
////////////////////////////////////////////////////////////////////////////////
// class template Int2Type
// Converts each integral constant into a unique type
// Invocation: Int2Type<v> where v is a compile-time constant integral
// Defines ‘value’, an enum that evaluates to v
////////////////////////////////////////////////////////////////////////////////
template <int v>
struct Int2Type
{
enum { value = v };
};
////////////////////////////////////////////////////////////////////////////////
// class template Type2Type
// Converts each type into a unique, insipid type
// Invocation Type2Type<T> where T is a type
// Defines the type OriginalType which maps back to T
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct Type2Type
{
typedef T OriginalType;
};
////////////////////////////////////////////////////////////////////////////////
// class template Select
// Selects one of two types based upon a boolean constant
// Invocation: Select<flag, T, U>::Result
// where:
// flag is a compile-time boolean constant
// T and U are types
// Result evaluates to T if flag is true, and to U otherwise.
////////////////////////////////////////////////////////////////////////////////
template <bool flag, typename T, typename U>
struct Select
{
typedef T Result;
};
template <typename T, typename U>
struct Select<false, T, U>
{
typedef U Result;
};
////////////////////////////////////////////////////////////////////////////////
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class T, class U>
struct ConversionHelper
{
typedef char Small;
struct Big { char dummy[2]; };
static Big Test(…);
static Small Test(U);
static T MakeT();
};
}
////////////////////////////////////////////////////////////////////////////////
// class template Conversion
// Figures out the conversion relationships between two types
// Invocations (T and U are types):
// a) Conversion<T, U>::exists
// returns (at compile time) true if there is an implicit conversion from T
// to U (example: Derived to Base)
// b) Conversion<T, U>::exists2Way
// returns (at compile time) true if there are both conversions from T
// to U and from U to T (example: int to char and back)
// c) Conversion<T, U>::sameType
// returns (at compile time) true if T and U represent the same type
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
template <class T, class U>
struct Conversion
{
typedef Private::ConversionHelper<T, U> H;
#if defined(MWERKS) && MWERKS < 0x3000
enum { exists = false };
#else
enum { exists = sizeof(typename H::Small) == sizeof((H::Test(H::MakeT()))) };
#endif
enum { exists2Way = exists && Conversion<U, T>::exists };
enum { sameType = false };
};
template <class T>
struct Conversion<T, T>
{
enum { exists = 1, exists2Way = 1, sameType = 1 };
};
template <class T>
struct Conversion<void, T>
{
enum { exists = 0, exists2Way = 0, sameType = 0 };
};
template <class T>
struct Conversion<T, void>
{
enum { exists = 1, exists2Way = 0, sameType = 0 };
};
template <>
struct Conversion<void, void>
{
public:
enum { exists = 1, exists2Way = 1, sameType = 1 };
};
////////////////////////////////////////////////////////////////////////////////
// class template SuperSubclass
// Invocation: SuperSubclass<B, D>::value where B and D are types.
// Returns true if B is a public base of D, or if B and D are aliases of the
// same type.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
template <class T, class U>
struct SuperSubclass
{
enum { value = (::Loki::Conversion<const volatile U, const volatile T>::exists &&
!::Loki::Conversion<const volatile T, const volatile void>::sameType) };
};
////////////////////////////////////////////////////////////////////////////////
// class template SuperSubclassStrict
// Invocation: SuperSubclassStrict<B, D>::value where B and D are types.
// Returns true if B is a public base of D.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////
template<class T,class U>
struct SuperSubclassStrict
{
enum { value = (::Loki::Conversion<const volatile U, const volatile T>::exists &&
!::Loki::Conversion<const volatile T, const volatile void>::sameType &&
!::Loki::Conversion<const volatile T, const volatile U>::sameType) };
};
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
// Returns true if B is a public base of D, or if B and D are aliases of the
// same type.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
// Deprecated: Use SuperSubclass class template instead.
////////////////////////////////////////////////////////////////////////////////
#define SUPERSUBCLASS(T, U)
::Loki::SuperSubclass<T,U>::value
////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS_STRICT
// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
// Returns true if B is a public base of D.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
// Deprecated: Use SuperSubclassStrict class template instead.
////////////////////////////////////////////////////////////////////////////////
#define SUPERSUBCLASS_STRICT(T, U)
::Loki::SuperSubclassStrict<T,U>::value
////////////////////////////////////////////////////////////////////////////////
// Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// November 22, 2001: minor change to support porting to boost
// November 22, 2001: fixed bug in Conversion<void, T>
// (credit due to Brad Town)
// November 23, 2001: (well it’s 12:01 am) fixed bug in SUPERSUBCLASS - added
// the volatile qualifier to be 100% politically correct
// September 16, 2002: Changed "const volatile" to "const volatile ", to enable
// conversion to succeed. Done earlier by MKH.
// Added SuperSubclass and SuperSubclassStrict templates. The corresponding
// macros are deprecated.
// Added extra parenthesis in sizeof in Conversion, to disambiguate function
// call from function declaration. T.S.
////////////////////////////////////////////////////////////////////////////////
#endif // TYPEMANIPINC