Benjamin Kaufmann's port

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@87 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
tslettebo 2003-01-10 01:33:21 +00:00
parent ca94249f94
commit 10c21af076
7 changed files with 348 additions and 201 deletions

View file

@ -13,7 +13,8 @@
// without express or implied warranty. // without express or implied warranty.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Last update: Oct 24, 2002 // Last update: Dec 08, 2002
#ifndef HIERARCHYGENERATORS_INC_ #ifndef HIERARCHYGENERATORS_INC_
#define HIERARCHYGENERATORS_INC_ #define HIERARCHYGENERATORS_INC_
@ -68,15 +69,40 @@ namespace Loki
// //
// See "Metaprogramming VC++ - more of Loki ported" from Mat Marcus // See "Metaprogramming VC++ - more of Loki ported" from Mat Marcus
// (http://lists.boost.org/MailArchives/boost/msg20915.php) // (http://lists.boost.org/MailArchives/boost/msg20915.php)
//
// Update:
// -------
// The first version of GenScatterHierarchy did not work with typelists
// containing equal types. The MSVC 6.0 erroneously complains about
// inaccessible base-classes (error C2584).
// This new version adds Dummy-classes to the left branch of the generated
// hierarchy to workaround this VC-Bug.
// It creates hierarchies like this:
//
// Holder<int> NullType
// \ /
//Holder<int> GenScatter<int> GenScatter<NullType>
// \ \ /
//VC_InaccessibleBase InheritFromTo
// \ |
//GenScatter<int> GenScatter<TYPELIST_1(int)>
// \ /
// InheritFromTo
// |
// |
//GenScatter<TYPELIST_2(int, int)>
//
// Of course this version of GenScatterHierarchy generates a lot more
// classes (5*n) than Alexandrescu's original implementation (3*n)
//
template <class TList, class Unit> class GenScatterHierarchy; template <class TList, class Unit> class GenScatterHierarchy;
namespace Private namespace Private
{ {
template <class T, class U> template <class T, class U>
class InheritFromTwo : public T, public U struct InheritFromTwo : public T, public U
{ {
public:
}; };
template <int tag> template <int tag>
@ -90,16 +116,34 @@ namespace Private
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper> struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
{ {
typedef typedef
InheritFromTwo < GenScatterHierarchy<typename T::Head, InheritFromTwo < VC_InaccessibleBase<GenScatterHierarchy<typename T::Head,
MetaFunctionWrapper>, MetaFunctionWrapper>, typename T::Tail>,
GenScatterHierarchy<typename T::Tail, GenScatterHierarchy<typename T::Tail,
MetaFunctionWrapper> MetaFunctionWrapper>
> type; > type;
typedef GenScatterHierarchy<typename T::Head, MetaFunctionWrapper> LeftBase; typedef VC_InaccessibleBase<GenScatterHierarchy<typename T::Head, MetaFunctionWrapper>,typename T::Tail> LeftBase;
typedef GenScatterHierarchy<typename T::Tail, MetaFunctionWrapper> RightBase; typedef GenScatterHierarchy<typename T::Tail, MetaFunctionWrapper> RightBase;
}; };
}; };
// Specialization for a typelist with only one element
template <>
struct GenScatterImpl<TL::Private::AtomList_ID>
{
template <class T, class MetaFunctionWrapper>
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
{
// for the last Holder-class no dummy class is needed.
typedef
InheritFromTwo < GenScatterHierarchy<typename T::Head,
MetaFunctionWrapper>,
GenScatterHierarchy<NullType,
MetaFunctionWrapper>
> type;
typedef GenScatterHierarchy<typename T::Head, MetaFunctionWrapper> LeftBase;
typedef GenScatterHierarchy<NullType, MetaFunctionWrapper> RightBase;
};
};
// Specialization for a single type // Specialization for a single type
template <> template <>
struct GenScatterImpl<TL::Private::NoneList_ID> struct GenScatterImpl<TL::Private::NoneList_ID>
@ -111,7 +155,9 @@ namespace Private
ApplyInnerType<MetaFunctionWrapper, AtomicType>::type type; ApplyInnerType<MetaFunctionWrapper, AtomicType>::type type;
typedef type LeftBase; typedef type LeftBase;
typedef EmptyType RightBase; typedef EmptyType RightBase;
//typedef AtomicType::THIS_SELECTED bla;
}; };
}; };
// Specialization for NullType // Specialization for NullType
@ -131,10 +177,7 @@ namespace Private
template <class T, class Unit> template <class T, class Unit>
class GenScatterHierarchy : public Private::GenScatterImpl class GenScatterHierarchy : public Private::GenScatterImpl
< <
IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID : IS_TYPELIST(T)::type_id
IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID :
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID :
TL::Private::NoneList_ID
>::template In<T, Unit>::type >::template In<T, Unit>::type
{ {
public: public:
@ -142,20 +185,14 @@ namespace Private
< <
TL::Private::IsTypelist<T>::value, T, void TL::Private::IsTypelist<T>::value, T, void
>::Result TList; >::Result TList;
typedef typename Private::GenScatterImpl
<
IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID :
IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID :
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID :
TL::Private::NoneList_ID
>::template In<T, Unit>::LeftBase LeftBase;
typedef typename Private::GenScatterImpl typedef typename Private::GenScatterImpl
< <
IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID : IS_TYPELIST(T)::type_id
IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID : >::template In<T, Unit>::LeftBase LeftBase;
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID : typedef typename Private::GenScatterImpl
TL::Private::NoneList_ID <
IS_TYPELIST(T)::type_id
>::template In<T, Unit>::RightBase RightBase; >::template In<T, Unit>::RightBase RightBase;
template <typename U> struct Rebind template <typename U> struct Rebind
@ -269,11 +306,12 @@ namespace Private
// If Do is not a template and H& is used as parameter // If Do is not a template and H& is used as parameter
// MSVC will give a linker error. // MSVC will give a linker error.
template <class T> template <class T>
static ResultType& Do(T& obj) static ResultType& Do(H& obj, T*)
{ {
typedef typename T::RightBase RightBase; //typedef typename T::RightBase RightBase;
//RightBase& rightBase = obj;
RightBase& rightBase = obj; RightBase& rightBase = obj;
return FieldHelper<i - 1>::template In<RightBase, Unit>::Do(rightBase); return FieldHelper<i - 1>::template In<RightBase, Unit>::Do(rightBase, (int*)0);
} }
}; };
}; };
@ -317,7 +355,7 @@ namespace Private
public: public:
template <class T> template <class T>
static ResultType& Do(T& obj) static ResultType& Do(H& obj, T*)
{ {
LeftBase& leftBase = obj; LeftBase& leftBase = obj;
return leftBase; return leftBase;
@ -334,17 +372,14 @@ namespace Private
// returns a reference to Unit<T>, where Unit is the template used to generate H // returns a reference to Unit<T>, where Unit is the template used to generate H
// and T is the i-th type in the typelist // and T is the i-th type in the typelist
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <unsigned int i, class TList, class UnitWrapper> template <unsigned int i, class TList, class UnitWrapper>
typename FieldHelper<i>::template In<GenScatterHierarchy<TList, UnitWrapper>,UnitWrapper>::ResultType& typename FieldHelper<i>::template In<GenScatterHierarchy<TList, UnitWrapper>,UnitWrapper>::ResultType&
Field(GenScatterHierarchy<TList, UnitWrapper>& obj) Field(GenScatterHierarchy<TList, UnitWrapper>& obj, Int2Type<i>)
{ {
typedef typename GenScatterHierarchy<TList, UnitWrapper> H; typedef typename GenScatterHierarchy<TList, UnitWrapper> H;
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj, (int*)0);
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template GenLinearHierarchy // class template GenLinearHierarchy
// Generates a linear hierarchy starting from a typelist and a template // Generates a linear hierarchy starting from a typelist and a template
@ -386,7 +421,8 @@ namespace Private
typedef typename TList::Tail Tail; typedef typename TList::Tail Tail;
public: public:
typedef ApplyInnerType2<Unit, Head, GenLinearHierarchy<Tail, Unit, Root> >::type Result; typedef typename
ApplyInnerType2<Unit, Head, GenLinearHierarchy<Tail, Unit, Root> >::type Result;
}; };
}; };
@ -400,7 +436,7 @@ namespace Private
typedef typename TList::Head Head; typedef typename TList::Head Head;
public: public:
typedef ApplyInnerType2<Unit,Head, Root>::type Result; typedef typename ApplyInnerType2<Unit,Head, Root>::type Result;
}; };
}; };
@ -417,13 +453,12 @@ namespace Private
> >
::template In<T, U, Root>::Result TempType; ::template In<T, U, Root>::Result TempType;
typedef typename typedef Private::VC_Base_Workaround<TempType, Dummy> type;
Private::VC_Base_Workaround<TempType, Dummy> type;
// this is nothing more than a typedef to the created hierarchy (TempType). // this is nothing more than a typedef to the created hierarchy (TempType).
// But if we try to inherit directly from TempType VC 6.0 // But if we try to inherit directly from TempType VC 6.0
// will produce a "Error C2516. : is not a legal base class." // will produce a "Error C2516. : is not a legal base class."
typedef type::LeftBase Base; typedef typename type::LeftBase Base;
}; };
} // namespace Private } // namespace Private
@ -450,11 +485,26 @@ namespace Private
} // namespace Loki } // namespace Loki
#if defined (_MSC_VER) && _MSC_VER <= 1300
#define FIELD(Obj, Nr) \
Field(Obj, Int2Type<Nr>())
#else
#define FIELD(Obj, Nr) \
Field<Nr>(Obj)
#endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Change log: // Change log:
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// September 16, 2002: Fixed dependent template, using "::template" syntax. T.S. // September 16, 2002: Fixed dependent template, using "::template" syntax. T.S.
// Oct 24, 2002: ported by Benjamin Kaufmann to MSVC 6 // Oct 24, 2002: ported by Benjamin Kaufmann to MSVC 6
// Dec 08, 2002: Fixed problems with MSVC6-Version of GenScatterHierarchy when
// used with typelists containing equal types. B.K.
// New Version is ugly :-(
// Dec 08, 2002: Interface changed for Field-Function. The old version does not
// work correctly due to the "Explicitly Specified Template
// Functions Not Overloaded Correctly"-Bug
// (Microsoft KB Article - 240871). B.K.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#undef IS_TYPELIST #undef IS_TYPELIST
#endif // HIERARCHYGENERATORS_INC_ #endif // HIERARCHYGENERATORS_INC_

View file

@ -1,3 +1,7 @@
// Last update: Dec 03, 2002
// Added qualification ::Loki::Private:: to types from the Private-Namespace
// Thanks to Adi Shavit
#ifndef MSVC6HELPERS__H #ifndef MSVC6HELPERS__H
#define MSVC6HELPERS__H #define MSVC6HELPERS__H
#if !defined (_MSC_VER) || _MSC_VER >= 1300 #if !defined (_MSC_VER) || _MSC_VER >= 1300
@ -7,6 +11,10 @@ namespace Loki
{ {
namespace Private namespace Private
{ {
template <class T, class U>
struct VC_InaccessibleBase : public T
{};
// workaround for the "Error C2516. : is not a legal base class" // workaround for the "Error C2516. : is not a legal base class"
// Use VC_Base_Workaround's LeftBase instead of the // Use VC_Base_Workaround's LeftBase instead of the
// alleged illegal base class. // alleged illegal base class.
@ -50,9 +58,9 @@ namespace Loki
{ template<class> struct In; }; { template<class> struct In; };
template< typename T1 > struct Result : public template< typename T1 > struct Result : public
VC_WORKAROUND< AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1> VC_WORKAROUND< ::Loki::Private::AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1>
{ {
typedef VC_WORKAROUND< AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1> Base; typedef VC_WORKAROUND< ::Loki::Private::AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1> Base;
}; };
}; };
@ -72,7 +80,7 @@ namespace Loki
{template<class T, class U> struct In; }; {template<class T, class U> struct In; };
template< typename T1, typename T2 > struct Result : public template< typename T1, typename T2 > struct Result : public
VC_WORKAROUND< AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1, T2> VC_WORKAROUND< ::Loki::Private::AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1, T2>
{ {
}; };
}; };
@ -88,9 +96,9 @@ namespace Loki
// i first saw this technique in boost's mpl library. // i first saw this technique in boost's mpl library.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<typename F, typename T1> template<typename F, typename T1>
struct Apply1 : Private::ApplyImpl1<F>::template Result<T1> struct Apply1 : ::Loki::Private::ApplyImpl1<F>::template Result<T1>
{ {
typedef typename Private::ApplyImpl1<F>::template Result<T1>::Base Base; typedef typename ::Loki::Private::ApplyImpl1<F>::template Result<T1>::Base Base;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template Apply2 // class template Apply2
@ -100,7 +108,7 @@ namespace Loki
// i first saw this technique in boost's mpl library. // i first saw this technique in boost's mpl library.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template<typename F, typename T1, typename T2> template<typename F, typename T1, typename T2>
struct Apply2 : Private::ApplyImpl2<F>::template Result<T1, T2> struct Apply2 : ::Loki::Private::ApplyImpl2<F>::template Result<T1, T2>
{ {
}; };
@ -121,7 +129,7 @@ namespace Loki
template<> struct Wrapper_VC<true> template<> struct Wrapper_VC<true>
{ template<class X> struct In; }; { template<class X> struct In; };
typedef typename typedef typename
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type; Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template ApplyInnerType2 // class template ApplyInnerType2
@ -139,7 +147,7 @@ namespace Loki
template<> struct Wrapper_VC<true> template<> struct Wrapper_VC<true>
{ template<class X, class Y> struct In; }; { template<class X, class Y> struct In; };
typedef typename typedef typename
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type; Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
}; };
template <class Wrapper, class T, class U, class V, class W> template <class Wrapper, class T, class U, class V, class W>
@ -150,8 +158,9 @@ namespace Loki
template<> struct Wrapper_VC<true> template<> struct Wrapper_VC<true>
{ template<class W, class X, class Y, class Z> struct In; }; { template<class W, class X, class Y, class Z> struct In; };
typedef typename typedef typename
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type; Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
}; };
} }
#endif #endif

View file

@ -1,5 +1,6 @@
Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors
------------------------------------------------------------------- -------------------------------------------------------------------
Version: 0.3
Introduction/Compatibility: Introduction/Compatibility:
--------------------------- ---------------------------
@ -26,6 +27,32 @@ you must add SmallObj.cpp to your project/makefile.
If you use Singletons with longevity you must add Singleton.cpp to your project/makefile. If you use Singletons with longevity you must add Singleton.cpp to your project/makefile.
Fixes:
------
Dec 08, 2002:
-------------
* In HierarchyGenerators.h: Sergey Khachatrian reported a bug
in GenScatterHierarchy when used with a typelist containing
equal types (e.g. GenScatterHierarchy<TYPELIST_2(int, int), UnitWrapper>
resp. Tuple<TYPELIST_2(int, int)>)
Fixing the bug I found another MSVC6-Problem in the Field-function.
The workaround for this problems results in an interface change.
please refer to the section "Interface changes" below for further information.
Dec 03, 2002
-------------
* In MSVC6Helpers.h: The original version failed to qualify some types from the
Private-Namespace.
Thanks to Adi Shavit for pointing that out
* In Threads.h: Changed wrong ctor/dtor names in ObjectLevelLockable.
Thanks to Adi Shavit for pointing that out
Nov 19, 2002:
-------------
* In SmartPtr.h: Changed template ctors. See Notes.
Notes: Notes:
------ ------
@ -37,7 +64,6 @@ C. explicit template argument specification for member- and nonmeber functions.
D. covariant return types. D. covariant return types.
E. Template parameters with a default type void E. Template parameters with a default type void
F. return statements with an expression of type cv in functions with a return type of cv void. F. return statements with an expression of type cv in functions with a return type of cv void.
G. Template-ctor resp. template assignment operator
Unfortunately the MSVC 6.0 supports neither of them. Unfortunately the MSVC 6.0 supports neither of them.
@ -88,6 +114,29 @@ Unfortunately the MSVC 6.0 supports neither of them.
[/code] [/code]
in this port. in this port.
Update:
-------
The MSVC 6.0 sometimes does not overload normal functions depending
on explicit argument specification correctly (see: Microsoft KB Article - 240871)
The following code demonstrates the problem:
[code]
template <unsigned i, class T>
void BugDemonstration(T p)
{
printf("BugDemonstration called with i = %d\n", i);
}
int main()
{
GenScatterHierarchy<TYPELIST_3(int, int, int), TestUnitWrapper> Bla;
// will always print: "BugDemonstration called with i = 2";
BugDemonstration<0>(Bla);
BugDemonstration<1>(Bla);
BugDemonstration<2>(Bla);
}
[/code]
As a workaround i added dummy-parameters.
D. Virtual functions that use covariant return types (e.g. return a pointer to Derived) D. Virtual functions that use covariant return types (e.g. return a pointer to Derived)
in the original library were changed so that they have exactly the in the original library were changed so that they have exactly the
@ -96,41 +145,64 @@ Unfortunately the MSVC 6.0 supports neither of them.
E. All template parameters that have a default type of void in the original lib now E. All template parameters that have a default type of void in the original lib now
have int as default type. have int as default type.
F. In Functor.h I changed a ResultType of type void to VoidAsType (a udt). This change is transparent F. In Functor.h I changed a ResultType of type void to VoidAsType (an udt). This change is transparent
for the user of Functor. for the user of Functor.
Because I could not think of any general and transparent workaround I followed different Because I could not think of any general and transparent workaround I followed different
strategies. In Visitor.h for example I created new classes (and macros) for the void-case. strategies. In Visitor.h for example I created new classes (and macros) for the void-case.
In other places (for example: MultiMethod.h) this port simply fails to support void as In other places (for example: MultiMethod.h) this port simply fails to support void as
return type :-( return type :-(
G. The MSVC 6.0 does not recognize a copy-ctor resp. a copy-assignment if a templated version Some words to template-ctors resp. template assignment operators:
is present. On the other hand the MSVC 6.0 allows explicit template specialization in class The MSVC 6.0 introduces an order-dependency for template ctor
scope. I used this "feature" as a workaround for code like this: resp. template assignemt operators.
[code] If you need both a copy-ctor and a template copy ctor (same for copy-assignment), then
template <class T> you *must* write the templated version first.
struct Foo So instead of
{ [code]
Foo(const Foo&); template <class T>
struct Foo
{
Foo(const Foo&)
{}
template <class U> template <class U>
Foo(const Foo<U>&); Foo(const Foo<U>& r)
}; {}
[/code] };
[/code]
Under MSVC 6.0 the above code becomes: you *need* to write:
[code] [code]
template <class T> template <class T>
struct Foo struct Foo
{ {
template <class U> template <class U>
Foo(const Foo<U>&); Foo(const Foo<U>& r)
{}
// copy-ctor for Foos with equal T Foo(const Foo& r)
// not valid c++ {}
template <> };
Foo(const Foo&); [/code]
};
[/code]
Many thanks to Nelson Elói for pointing that out and for providing me
with this solution.
The above solution unfortunately does not work if the template ctor does not have
the form of a copy-ctor. If you write something like this (as in the functor-class):
[code]
template <class T>
struct Foo
{
template <class Fun>
Foo(Fun r)
{}
Foo(const Foo& r)
{}
};
[/code]
then the VC will no longer find a copy-ctor.
Because of this, i can't use Nelson Elói's solution in Functor.h
Interface changes: Interface changes:
------------------ ------------------
@ -180,6 +252,44 @@ Interface changes:
a nested-template class called 'In'. 'In' should only contain a typedef to the a nested-template class called 'In'. 'In' should only contain a typedef to the
concrete Unit. concrete Unit.
Update:
The port's original version of GenScatterHierarchy does not work when used
with typelists containing equal types.
The problem is due to a VC bug. The VC fails to compile code similar
to this, although it is perfectly legal.
[code]
template <class T>
class Wrapper
{};
template <class T>
struct B : public Wrapper<T>
{};
// ERROR: 'A<T>' : direct base 'Wrapper<T>' is inaccessible; already a base of 'B<T>'
template <class T>
class A : public B<T>, public Wrapper<T>
{};
[/code]
Unfortunately my workaround has a big drawback.
GenScatterHierarchy now has to generate a lot more classes.
Alexandrescu's original implementation generates 3*n classes (n - number of types in the typelist)
The old version of my port creates 4 * n + 1
The new version will create 5 * n
The fix also reveals the "Explicitly Specified Template Functions Not Overloaded Correctly"-Bug
(Microsoft KB Article - 240871) in the Field-Function taking a nontype int Parameter.
This leads to an interface change:
Instead of: Field<0>(obj)
one now has to write
Field(obj, Int2Type<0>());
I added a macro FIELD. Using this macro one can write
FIELD(obj, 0)
6. Factory.h 6. Factory.h
* The Error-Policy for Factory and CloneFactory is no longer a template template parameter. * The Error-Policy for Factory and CloneFactory is no longer a template template parameter.

View file

@ -13,21 +13,18 @@
// without express or implied warranty. // without express or implied warranty.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Last update: Oct 26, 2002 // Last update: Nov 19, 2002
// replaced all template template parameters with 'normal' parameters // replaced all template template parameters with 'normal' parameters
// For each Policy there is now a wrapper-class (non template class) // For each Policy there is now a wrapper-class (non template class)
// containing a nested template class called In which // containing a nested template class called In which
// provides a typedef (type) to the real Policy-class // provides a typedef (type) to the real Policy-class
// //
// VC special: The MSVC 6.0 has problems with template ctors resp. template // VC special: The MSVC 6.0 introduces an order-dependency for template ctor
// assignemt operators. If there exists a template copy ctor (a template op=) the // resp. template assignemt operators.
// compiler will complain about a non-template version. On the other hand, // If you need both a copy-ctor and a template copy ctor (same for copy-assignment), then
// if one does not provide a non-template version and one tries to // you *must* write the templated version first.
// initialize a new object with one having the same type the compiler will synthesize // So instead of
// a default version (the same for assignment).
// Because the MSVC allows explicit specialization in class scope i used
// this as a workaround.
// Instead of:
// template <class T> // template <class T>
// struct Foo // struct Foo
// { // {
@ -37,19 +34,21 @@
// Foo(const Foo<U>& r) // Foo(const Foo<U>& r)
// {} // {}
// }; // };
// // you *need* to write:
// this port uses:
//
// template <class T> // template <class T>
// struct Foo // struct Foo
// { // {
// template <class U> // template <class U>
// Foo(const Foo<U>& r) // Foo(const Foo<U>& r)
// {} // {}
// template <> //
// Foo(const Foo& r) // Foo(const Foo& r)
// {} // {}
// }; // };
//
// Many thanks to Nelson Elói for pointing that out and for providing me
// with this solution
#ifndef SMARTPTR_INC_ #ifndef SMARTPTR_INC_
#define SMARTPTR_INC_ #define SMARTPTR_INC_
@ -93,18 +92,15 @@ namespace Loki
// The storage policy doesn't initialize the stored pointer // The storage policy doesn't initialize the stored pointer
// which will be initialized by the OwnershipPolicy's Clone fn // which will be initialized by the OwnershipPolicy's Clone fn
#if !defined(_MSC_VER)
DefaultSPStorage(const DefaultSPStorage&) // do not alter the order of the following two constructors
{} // otherwise the MSVC 6.0 will not compile the class.
#endif
template <class U> template <class U>
DefaultSPStorage(const DefaultSPStorage<U>&) DefaultSPStorage(const DefaultSPStorage<U>&) {}
{}
#if _MSC_VER <= 1200
template <>
DefaultSPStorage(const DefaultSPStorage&) DefaultSPStorage(const DefaultSPStorage&)
{} {}
#endif
DefaultSPStorage(const StoredType& p) : pointee_(p) {} DefaultSPStorage(const StoredType& p) : pointee_(p) {}
PointerType operator->() const { return pointee_; } PointerType operator->() const { return pointee_; }
@ -166,11 +162,8 @@ namespace Loki
*pCount_ = 1; *pCount_ = 1;
} }
#if !defined(_MSC_VER) // do not alter the order of the following two constructors
RefCounted(const RefCounted& rhs) // otherwise the MSVC 6.0 will fail to compile the class.
: pCount_(rhs.pCount_)
{}
#endif
// MWCW lacks template friends, hence the following kludge // MWCW lacks template friends, hence the following kludge
template <typename P1> template <typename P1>
@ -178,12 +171,10 @@ namespace Loki
: pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_) : pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
{} {}
#if _MSC_VER <= 1200
template<>
RefCounted(const RefCounted& rhs) RefCounted(const RefCounted& rhs)
: pCount_(rhs.pCount_) : pCount_(rhs.pCount_)
{} {}
#endif
P Clone(const P& val) P Clone(const P& val)
{ {
++*pCount_; ++*pCount_;
@ -977,10 +968,8 @@ namespace Private
} }
#if !defined(_MSC_VER) // do not alter the order of the following three constructors
SmartPtr(CopyArg& rhs) // otherwise the MSVC 6.0 will fail to compile the class.
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
#endif
template template
< <
typename T1, typename T1,
@ -1005,28 +994,15 @@ namespace Private
: SP(rhs), OP(rhs), KP(rhs), CP(rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); } { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
#if _MSC_VER <= 1200
template <>
SmartPtr(CopyArg& rhs) SmartPtr(CopyArg& rhs)
: SP(rhs), OP(rhs), KP(rhs), CP(rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
#endif
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); } { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
SmartPtr(ByRef<SmartPtr> rhs)
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
{}
operator ByRef<SmartPtr>() operator ByRef<SmartPtr>()
{ return ByRef<SmartPtr>(*this); } { return ByRef<SmartPtr>(*this); }
#if !defined(_MSC_VER)
SmartPtr& operator=(CopyArg& rhs)
{ // do not alter the order of the following three copy-assignment operators
SmartPtr temp(rhs); // otherwise the MSVC 6.0 will fail to compile the class.
temp.Swap(*this);
return *this;
}
#endif
template template
< <
typename T1, typename T1,
@ -1057,15 +1033,13 @@ namespace Private
temp.Swap(*this); temp.Swap(*this);
return *this; return *this;
} }
#if _MSC_VER <= 1200
template<>
SmartPtr& operator=(CopyArg& rhs) SmartPtr& operator=(CopyArg& rhs)
{ {
SmartPtr temp(rhs); SmartPtr temp(rhs);
temp.Swap(*this); temp.Swap(*this);
return *this; return *this;
} }
#endif
void Swap(SmartPtr& rhs) void Swap(SmartPtr& rhs)
{ {
OP::Swap(rhs); OP::Swap(rhs);

View file

@ -8,10 +8,13 @@
// affects only default template arguments // affects only default template arguments
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Last update: Oct 07, 2002 // Last update: Dec 03, 2002
// note: In this VC 6 port all template policies become non-templates with // note: In this VC 6 port all template policies become non-templates with
// either member-template functions or a nested template struct named In // either member-template functions or a nested template struct named In
// Changed wrong ctor/dtor names in ObjectLevelLockable.
// Thanks to Adi Shavit for pointing that out
#ifndef DEFAULT_THREADING #ifndef DEFAULT_THREADING
#define DEFAULT_THREADING /**/ ::Loki::SingleThreaded #define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
#endif #endif
@ -90,12 +93,12 @@ namespace Loki
CRITICAL_SECTION mtx_; CRITICAL_SECTION mtx_;
public: public:
ObjectLevelLockable() In()
{ {
::InitializeCriticalSection(&mtx_); ::InitializeCriticalSection(&mtx_);
} }
~ObjectLevelLockable() ~In()
{ {
::DeleteCriticalSection(&mtx_); ::DeleteCriticalSection(&mtx_);
} }

View file

@ -37,6 +37,7 @@ namespace Loki
template <int v> template <int v>
struct Int2Type struct Int2Type
{ {
Int2Type() {}
enum { value = v }; enum { value = v };
}; };

View file

@ -173,7 +173,7 @@ namespace Loki
class TypeTraits class TypeTraits
{ {
private: private:
// static T MakeT(...); static T MakeT(...);
template <class U> struct Wrap{}; template <class U> struct Wrap{};
struct pointer_helper struct pointer_helper
{ {
@ -232,8 +232,8 @@ namespace Loki
enum {isReference = sizeof( enum {isReference = sizeof(
is_reference_helper2( is_reference_helper2(
is_reference_helper1(Wrap<T>()))) == sizeof(Private::YES)}; is_reference_helper1(Wrap<T>()))) == sizeof(Private::YES)};
// enum {isPointer = sizeof(is_pointer(MakeT())) == sizeof(Private::YES)}; enum {isPointer = sizeof(is_pointer(MakeT())) == sizeof(Private::YES)};
// enum {isMemberPointer = sizeof(is_pointer2member(MakeT())) == sizeof(Private::YES)}; enum {isMemberPointer = sizeof(is_pointer2member(MakeT())) == sizeof(Private::YES)};
enum {isArray = sizeof( enum {isArray = sizeof(
is_array_helper1( is_array_helper1(
is_array_helper2(Wrap<T>()))) == sizeof(Private::YES)}; is_array_helper2(Wrap<T>()))) == sizeof(Private::YES)};
@ -264,7 +264,7 @@ namespace Loki
isVolatile = isVolatile =
sizeof(is_volatile(Wrap<T>())) == sizeof(Private::YES) sizeof(is_volatile(Wrap<T>())) == sizeof(Private::YES)
}; };
enum { isScalar = isStdArith /* || isPointer */ /* || isMemberPointer */ }; enum { isScalar = isStdArith || isPointer || isMemberPointer};
private: private:
typedef typename Private::AdjReference<isReference || isVoid>:: typedef typename Private::AdjReference<isReference || isVoid>::
template In<T>::Result AdjType; template In<T>::Result AdjType;