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.
////////////////////////////////////////////////////////////////////////////////
// Last update: Oct 24, 2002
// Last update: Dec 08, 2002
#ifndef HIERARCHYGENERATORS_INC_
#define HIERARCHYGENERATORS_INC_
@ -68,15 +69,40 @@ namespace Loki
//
// See "Metaprogramming VC++ - more of Loki ported" from Mat Marcus
// (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;
namespace Private
{
template <class T, class U>
class InheritFromTwo : public T, public U
{
public:
struct InheritFromTwo : public T, public U
{
};
template <int tag>
@ -90,16 +116,34 @@ namespace Private
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
{
typedef
InheritFromTwo < GenScatterHierarchy<typename T::Head,
MetaFunctionWrapper>,
InheritFromTwo < VC_InaccessibleBase<GenScatterHierarchy<typename T::Head,
MetaFunctionWrapper>, typename T::Tail>,
GenScatterHierarchy<typename T::Tail,
MetaFunctionWrapper>
> 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;
};
};
// 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
template <>
struct GenScatterImpl<TL::Private::NoneList_ID>
@ -111,7 +155,9 @@ namespace Private
ApplyInnerType<MetaFunctionWrapper, AtomicType>::type type;
typedef type LeftBase;
typedef EmptyType RightBase;
//typedef AtomicType::THIS_SELECTED bla;
};
};
// Specialization for NullType
@ -127,14 +173,11 @@ namespace Private
};
};
} // end namespace Private
template <class T, class Unit>
class GenScatterHierarchy : public 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
IS_TYPELIST(T)::type_id
>::template In<T, Unit>::type
{
public:
@ -142,28 +185,22 @@ namespace Private
<
TL::Private::IsTypelist<T>::value, T, void
>::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
<
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;
typedef typename Private::GenScatterImpl
<
IS_TYPELIST(T)::type_id
>::template In<T, Unit>::LeftBase LeftBase;
typedef typename Private::GenScatterImpl
<
IS_TYPELIST(T)::type_id
>::template In<T, Unit>::RightBase RightBase;
template <typename U> struct Rebind
{
typedef ApplyInnerType<Unit, U>::type Result;
};
};
////////////////////////////////////////////////////////////////////////////////
// function template Field
// 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
// MSVC will give a linker error.
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;
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:
template <class T>
static ResultType& Do(T& obj)
static ResultType& Do(H& obj, T*)
{
LeftBase& leftBase = obj;
return leftBase;
@ -334,17 +372,14 @@ namespace Private
// 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
////////////////////////////////////////////////////////////////////////////////
template <unsigned int i, class TList, class UnitWrapper>
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;
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj);
typedef typename GenScatterHierarchy<TList, UnitWrapper> H;
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj, (int*)0);
}
////////////////////////////////////////////////////////////////////////////////
// class template GenLinearHierarchy
// Generates a linear hierarchy starting from a typelist and a template
@ -386,7 +421,8 @@ namespace Private
typedef typename TList::Tail Tail;
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;
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;
typedef typename
Private::VC_Base_Workaround<TempType, Dummy> type;
typedef Private::VC_Base_Workaround<TempType, Dummy> type;
// this is nothing more than a typedef to the created hierarchy (TempType).
// But if we try to inherit directly from TempType VC 6.0
// will produce a "Error C2516. : is not a legal base class."
typedef type::LeftBase Base;
typedef typename type::LeftBase Base;
};
} // namespace Private
@ -450,11 +485,26 @@ namespace Private
} // 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:
// 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.
// 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
#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
#define MSVC6HELPERS__H
#if !defined (_MSC_VER) || _MSC_VER >= 1300
@ -7,18 +11,22 @@ namespace Loki
{
namespace Private
{
template <class T, class U>
struct VC_InaccessibleBase : public T
{};
// 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.
template <class T, class U>
struct VC_Base_Workaround : public T, public U
{
typedef T LeftBase;
};
// MSVC 6.0 does not allow the return of
// expressions of type "cv void" in a functions with a return
// type of cv void (6.6.3).
// expressions of type "cv void" in a functions with a return
// type of cv void (6.6.3).
// Functor.h uses this Type as a workaround.
struct VoidAsType {};
@ -50,10 +58,10 @@ namespace Loki
{ template<class> struct In; };
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< 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.
////////////////////////////////////////////////////////////////////////////////
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
@ -100,9 +108,9 @@ namespace Loki
// i first saw this technique in boost's mpl library.
////////////////////////////////////////////////////////////////////////////////
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
{
template<bool> struct Wrapper_VC : Wrapper {};
template<> struct Wrapper_VC<true>
{ template<class X> struct In; };
typedef typename
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type;
typedef typename
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type;
};
////////////////////////////////////////////////////////////////////////////////
// class template ApplyInnerType2
@ -135,23 +143,24 @@ namespace Loki
struct ApplyInnerType2
{
template<bool> struct Wrapper_VC : Wrapper {};
template<> struct Wrapper_VC<true>
{ template<class X, class Y> struct In; };
typedef typename
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
typedef typename
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
};
template <class Wrapper, class T, class U, class V, class W>
struct ApplyInnerType4
{
template<bool> struct Wrapper_VC : Wrapper {};
template<> struct Wrapper_VC<true>
{ template<class W, class X, class Y, class Z> struct In; };
typedef typename
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
typedef typename
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
};
}
#endif

View file

@ -1,11 +1,12 @@
Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors
-------------------------------------------------------------------
Version: 0.3
Introduction/Compatibility:
---------------------------
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
compatible to the original library and therefore code using this port *cannot* generally be
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
used together with the original lib.
This is, of course, a great pity.
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:
--------
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
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.
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.
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:
------
@ -37,18 +64,17 @@ C. explicit template argument specification for member- and nonmeber functions.
D. covariant return types.
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.
G. Template-ctor resp. template assignment operator
Unfortunately the MSVC 6.0 supports neither of them.
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
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 :-)
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
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
allow something like this:
@ -58,17 +84,17 @@ Unfortunately the MSVC 6.0 supports neither of them.
{
// 'error C1001 - Internal Compiler Error' here
typedef typename APolicy::template In<T> type;
};
};
[/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,
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
argument specification. These dummy-Parameters help the compiler in deducing the 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
parameters that otherwise need to be explicitly specified.
Example:
[code]
@ -88,103 +114,187 @@ Unfortunately the MSVC 6.0 supports neither of them.
[/code]
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)
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).
E. All template parameters that have a default type of void in the original lib now
have int as default type.
F. In Functor.h I changed a ResultType of type void to VoidAsType (a udt). This change is transparent
for the user of Functor.
F. In Functor.h I changed a ResultType of type void to VoidAsType (an udt). This change is transparent
for the user of Functor.
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.
In other places (for example: MultiMethod.h) this port simply fails to support void as
return type :-(
G. The MSVC 6.0 does not recognize a copy-ctor resp. a copy-assignment if a templated version
is present. On the other hand the MSVC 6.0 allows explicit template specialization in class
scope. I used this "feature" as a workaround for code like this:
[code]
template <class T>
struct Foo
{
Foo(const Foo&);
template <class U>
Foo(const Foo<U>&);
};
[/code]
Under MSVC 6.0 the above code becomes:
[code]
template <class T>
struct Foo
{
template <class U>
Foo(const Foo<U>&);
Some words to template-ctors resp. template assignment operators:
The MSVC 6.0 introduces an order-dependency for template ctor
resp. template assignemt operators.
If you need both a copy-ctor and a template copy ctor (same for copy-assignment), then
you *must* write the templated version first.
So instead of
[code]
template <class T>
struct Foo
{
Foo(const Foo&)
{}
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)
{}
// copy-ctor for Foos with equal T
// not valid c++
template <>
Foo(const Foo&);
};
[/code]
Foo(const Foo& r)
{}
};
[/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:
------------------
1. In Threads.h:
* Thread-Policies changed from class templates to normal classes containing a
nested class template 'In'.
* Thread-Policies changed from class templates to normal classes containing a
nested class template 'In'.
consequences:
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)
2. In Singleton.h:
* The Creation- and Lifetime-Policies are no longer class templates. Instead they all use
Member-Templates.
* The Creation- and Lifetime-Policies are no longer class templates. Instead they all use
Member-Templates.
consequences:
Again this change will only break new Policies when switching to the
original library.
3. In Functor.h:
* No covariant return types.
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.
4. TypeTraits.h
4. TypeTraits.h
* Because VC 6.0 lacks partial template specialization, the TypeTraits-Class provides not
all the stuff provided by the original library's version.
5. HierarchyGenerator.h
* I used Mat Marcus' approach to port GenScatterHierarchy.
See http://lists.boost.org/MailArchives/boost/msg20915.php) for the consequences.
* Same for GenLinearHierarchy
* Unit is no longer a template template parameter.
consequences:
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
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
* 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:
This change will only break new Policies when switching to the
original library.
@ -192,7 +302,7 @@ Interface changes:
7. AbstractFactory.h
* no covariant return types
* no template template parameters
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
@ -203,7 +313,7 @@ Interface changes:
ConcProduct* p = aFactory.Create<ConcProduct>();
to
ConcProduct* p = aFactory.Create((ConcProduct*)0);
8. SmartPtr.h
@ -214,7 +324,7 @@ Interface changes:
9. Visitor.h
* no template template parameters
* no template template parameters
(see 7.for a description of the consequences)
* 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.
* 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).

View file

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

View file

@ -8,10 +8,13 @@
// 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
// 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
#define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
#endif
@ -90,12 +93,12 @@ namespace Loki
CRITICAL_SECTION mtx_;
public:
ObjectLevelLockable()
In()
{
::InitializeCriticalSection(&mtx_);
}
~ObjectLevelLockable()
~In()
{
::DeleteCriticalSection(&mtx_);
}

View file

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

View file

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