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
@ -127,14 +173,11 @@ namespace Private
}; };
}; };
} // end namespace Private } // end 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,28 +185,22 @@ namespace Private
< <
TL::Private::IsTypelist<T>::value, T, void TL::Private::IsTypelist<T>::value, T, void
>::Result TList; >::Result TList;
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 == TL::Private::AtomList_ID ? TL::Private::Typelist_ID : IS_TYPELIST(T)::type_id
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID : >::template In<T, Unit>::LeftBase LeftBase;
TL::Private::NoneList_ID typedef typename Private::GenScatterImpl
>::template In<T, Unit>::LeftBase LeftBase; <
IS_TYPELIST(T)::type_id
typedef typename Private::GenScatterImpl >::template In<T, Unit>::RightBase RightBase;
<
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>::RightBase RightBase;
template <typename U> struct Rebind template <typename U> struct Rebind
{ {
typedef ApplyInnerType<Unit, U>::type Result; typedef ApplyInnerType<Unit, U>::type Result;
}; };
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// function template Field // function template Field
// Accesses a field in an object of a type generated with GenScatterHierarchy // Accesses a field in an object of a type generated with GenScatterHierarchy
@ -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,18 +11,22 @@ 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.
template <class T, class U> template <class T, class U>
struct VC_Base_Workaround : public T, public U struct VC_Base_Workaround : public T, public U
{ {
typedef T LeftBase; typedef T LeftBase;
}; };
// MSVC 6.0 does not allow the return of // MSVC 6.0 does not allow the return of
// expressions of type "cv void" in a functions with a return // expressions of type "cv void" in a functions with a return
// type of cv void (6.6.3). // type of cv void (6.6.3).
// Functor.h uses this Type as a workaround. // Functor.h uses this Type as a workaround.
struct VoidAsType {}; struct VoidAsType {};
@ -50,10 +58,10 @@ 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,9 +108,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, 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>
{ {
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -117,11 +125,11 @@ namespace Loki
struct ApplyInnerType struct ApplyInnerType
{ {
template<bool> struct Wrapper_VC : Wrapper {}; template<bool> struct Wrapper_VC : Wrapper {};
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
@ -135,23 +143,24 @@ namespace Loki
struct ApplyInnerType2 struct ApplyInnerType2
{ {
template<bool> struct Wrapper_VC : Wrapper {}; template<bool> struct Wrapper_VC : Wrapper {};
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>
struct ApplyInnerType4 struct ApplyInnerType4
{ {
template<bool> struct Wrapper_VC : Wrapper {}; template<bool> struct Wrapper_VC : Wrapper {};
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,11 +1,12 @@
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:
--------------------------- ---------------------------
This is a partial MSVC 6.0 Sp5 compatible port of Andrei Alexandrescu's excellent Loki Library. This is a partial MSVC 6.0 Sp5 compatible port of Andrei Alexandrescu's excellent Loki Library.
Because I could not retain the originial interface in all places, this port is not Because I could not retain the originial interface in all places, this port is not
compatible to the original library and therefore code using this port *cannot* generally be compatible to the original library and therefore code using this port *cannot* generally be
used together with the original lib. used together with the original lib.
This is, of course, a great pity. This is, of course, a great pity.
So if you know of a complete and full interface-compatible VC 6.0 So if you know of a complete and full interface-compatible VC 6.0
@ -13,19 +14,45 @@ port or if you know how to improve this port, please let me know.
Contact: Contact:
-------- --------
For any suggestions, bug reports, comments and questions please email me to For any suggestions, bug reports, comments and questions please email me to
Hume@c-plusplus.de Hume@c-plusplus.de
Using this port: Using this port:
---------------- ----------------
To use this port, simply extract the files from the archive, give your compiler access to To use this port, simply extract the files from the archive, give your compiler access to
their path, and include them appropriately in your code via #include. their path, and include them appropriately in your code via #include.
If you use the small object allocator directly or indirectly (through the Functor class) If you use the small object allocator directly or indirectly (through the Functor class)
you must add SmallObj.cpp to your project/makefile. 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,18 +64,17 @@ 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.
A. I used various techniques to simulate partial template specialization. In some cases A. I used various techniques to simulate partial template specialization. In some cases
these techniques allowed me to retain the original interfaces but often that was not these techniques allowed me to retain the original interfaces but often that was not
possible (or better: i did not find a proper solution). In any case it leads possible (or better: i did not find a proper solution). In any case it leads
to increasing code complexity :-) to increasing code complexity :-)
B. One way to simulate template template parameters is to replace the template class with B. One way to simulate template template parameters is to replace the template class with
a normal class containing a nested template class. You then move the original functionality a normal class containing a nested template class. You then move the original functionality
to the nested class. to the nested class.
The problem with this approach is MSVC's 'dependent template typedef bug'. MSVC 6.0 does not The problem with this approach is MSVC's 'dependent template typedef bug'. MSVC 6.0 does not
allow something like this: allow something like this:
@ -58,17 +84,17 @@ Unfortunately the MSVC 6.0 supports neither of them.
{ {
// 'error C1001 - Internal Compiler Error' here // 'error C1001 - Internal Compiler Error' here
typedef typename APolicy::template In<T> type; typedef typename APolicy::template In<T> type;
}; };
[/code] [/code]
To make a long story short, I finally decided to use boost::mpl's apply-technique to To make a long story short, I finally decided to use boost::mpl's apply-technique to
simulate template template parameters. This approach works fine with MSVC 6.0. But be warned, simulate template template parameters. This approach works fine with MSVC 6.0. But be warned,
this technique uses not valid C++. this technique uses not valid C++.
Of course, replacing template template parameters always results in some interface changes. Of course, replacing template template parameters always results in some interface changes.
C. I added dummy-Parameters to (Member-)Functions that depend on explicit template C. I added dummy-Parameters to (Member-)Functions that depend on explicit template
argument specification. These dummy-Parameters help the compiler in deducing the template argument specification. These dummy-Parameters help the compiler in deducing the template
parameters that otherwise need to be explicitly specified. parameters that otherwise need to be explicitly specified.
Example: Example:
[code] [code]
@ -88,103 +114,187 @@ 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
same return type as the original virtual function (e.g. return a pointer to Base). same return type as the original virtual function (e.g. return a pointer to Base).
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>
Under MSVC 6.0 the above code becomes: Foo(const Foo<U>& r)
[code] {}
template <class T> };
struct Foo [/code]
{ you *need* to write:
template <class U> [code]
Foo(const Foo<U>&); template <class T>
struct Foo
{
template <class 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:
------------------ ------------------
1. In Threads.h: 1. In Threads.h:
* Thread-Policies changed from class templates to normal classes containing a * Thread-Policies changed from class templates to normal classes containing a
nested class template 'In'. nested class template 'In'.
consequences: consequences:
This change is not very dramatic because it won't break code using this port when This change is not very dramatic because it won't break code using this port when
switching to the original library (only new Thread-Policies must be changed) switching to the original library (only new Thread-Policies must be changed)
2. In Singleton.h: 2. In Singleton.h:
* The Creation- and Lifetime-Policies are no longer class templates. Instead they all use * The Creation- and Lifetime-Policies are no longer class templates. Instead they all use
Member-Templates. Member-Templates.
consequences: consequences:
Again this change will only break new Policies when switching to the Again this change will only break new Policies when switching to the
original library. original library.
3. In Functor.h: 3. In Functor.h:
* No covariant return types. * No covariant return types.
consequences: consequences:
DoClone always returns a FunctorImplBase<R, ThreadingModel>* where R is the functor's return DoClone always returns a FunctorImplBase<R, ThreadingModel>* where R is the functor's return
type and ThreadingModel its current ThreadingModel. type and ThreadingModel its current ThreadingModel.
4. TypeTraits.h 4. TypeTraits.h
* Because VC 6.0 lacks partial template specialization, the TypeTraits-Class provides not * Because VC 6.0 lacks partial template specialization, the TypeTraits-Class provides not
all the stuff provided by the original library's version. all the stuff provided by the original library's version.
5. HierarchyGenerator.h 5. HierarchyGenerator.h
* I used Mat Marcus' approach to port GenScatterHierarchy. * I used Mat Marcus' approach to port GenScatterHierarchy.
See http://lists.boost.org/MailArchives/boost/msg20915.php) for the consequences. See http://lists.boost.org/MailArchives/boost/msg20915.php) for the consequences.
* Same for GenLinearHierarchy * Same for GenLinearHierarchy
* Unit is no longer a template template parameter. * Unit is no longer a template template parameter.
consequences: consequences:
For every concrete unit-template there must be a normal class containing For every concrete unit-template there must be a normal class containing
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.
Use a class with member-templates instead. Use a class with member-templates instead.
consequences: consequences:
This change will only break new Policies when switching to the This change will only break new Policies when switching to the
original library. original library.
@ -192,7 +302,7 @@ Interface changes:
7. AbstractFactory.h 7. AbstractFactory.h
* no covariant return types * no covariant return types
* no template template parameters * no template template parameters
For every concrete Factory-Unit there must be a normal class containing For every concrete Factory-Unit there must be a normal class containing
a nested-template class called 'In'. 'In' shall contain a typedef to the a nested-template class called 'In'. 'In' shall contain a typedef to the
@ -203,7 +313,7 @@ Interface changes:
ConcProduct* p = aFactory.Create<ConcProduct>(); ConcProduct* p = aFactory.Create<ConcProduct>();
to to
ConcProduct* p = aFactory.Create((ConcProduct*)0); ConcProduct* p = aFactory.Create((ConcProduct*)0);
8. SmartPtr.h 8. SmartPtr.h
@ -214,7 +324,7 @@ Interface changes:
9. Visitor.h 9. Visitor.h
* no template template parameters * no template template parameters
(see 7.for a description of the consequences) (see 7.for a description of the consequences)
* This port fails to correctly support void return types. As a workaround it provides * This port fails to correctly support void return types. As a workaround it provides
@ -229,7 +339,7 @@ Interface changes:
* This port does not support functions with return type void. * This port does not support functions with return type void.
* dummy parameters were added to functions that otherwise would depend on * dummy parameters were added to functions that otherwise would depend on
explicit template argument specification (14.8.1). explicit template argument specification (14.8.1).

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_)
{} // MWCW lacks template friends, hence the following kludge
#endif
// 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_;
@ -976,11 +967,9 @@ 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;