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,21 +185,15 @@ 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 <
>::template In<T, Unit>::RightBase RightBase; IS_TYPELIST(T)::type_id
>::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>
template <class U> struct Foo
Foo(const Foo<U>&); {
}; Foo(const Foo&)
[/code] {}
template <class U>
Foo(const Foo<U>& r)
{}
};
[/code]
you *need* to write:
[code]
template <class T>
struct Foo
{
template <class U>
Foo(const Foo<U>& r)
{}
Under MSVC 6.0 the above code becomes: Foo(const Foo& r)
[code] {}
template <class T> };
struct Foo [/code]
{
template <class U>
Foo(const Foo<U>&);
// copy-ctor for Foos with equal T Many thanks to Nelson Elói for pointing that out and for providing me
// not valid c++ with this solution.
template <>
Foo(const Foo&);
};
[/code]
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,19 +92,16 @@ 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)
// do not alter the order of the following two constructors
// otherwise the MSVC 6.0 will not compile the class.
template <class U>
DefaultSPStorage(const DefaultSPStorage<U>&) {}
DefaultSPStorage(const DefaultSPStorage&) DefaultSPStorage(const DefaultSPStorage&)
{} {}
#endif
template <class U> DefaultSPStorage(const StoredType& p) : pointee_(p) {}
DefaultSPStorage(const DefaultSPStorage<U>&)
{}
#if _MSC_VER <= 1200
template <>
DefaultSPStorage(const DefaultSPStorage&)
{}
#endif
DefaultSPStorage(const StoredType& p) : pointee_(p) {}
PointerType operator->() const { return pointee_; } PointerType operator->() const { return pointee_; }
@ -166,24 +162,19 @@ 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>
RefCounted(const RefCounted<P1>& rhs) RefCounted(const RefCounted<P1>& rhs)
: 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,29 +994,16 @@ 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); template
return *this;
}
#endif
template
< <
typename T1, typename T1,
class OP1, class OP1,
@ -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,7 +37,8 @@ namespace Loki
template <int v> template <int v>
struct Int2Type struct Int2Type
{ {
enum { value = v }; Int2Type() {}
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;