Loki/MSVC/1200
humesikkins 1d58eef03d different workaround for void returns than functor.h
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@105 7ec92016-0320-0410-acc4-a06ded1c099a
2003-02-27 15:55:21 +00:00
..
AbstractFactory.h replaced pointer-dummy parameters with Type2Type-parameters 2003-02-27 15:53:45 +00:00
AssocVector.h Benjamin Kaufmann's port 2003-01-06 02:26:33 +00:00
EmptyType.h Benjamin Kaufmann's port 2003-01-06 02:26:33 +00:00
Factory.h Added missing parameter to OnUnknownType 2003-02-27 15:53:29 +00:00
Functor.h new more stable version 2003-02-27 15:52:58 +00:00
FunctorOld.h different workaround for void returns than functor.h 2003-02-27 15:55:21 +00:00
HierarchyGenerators.h Benjamin Kaufmann's port 2003-01-10 01:33:21 +00:00
MSVC6Helpers.h Benjamin Kaufmann's port 2003-01-10 01:33:21 +00:00
MultiMethods.h added support for return type void 2003-02-27 15:51:56 +00:00
NullType.h Benjamin Kaufmann's port 2003-01-06 02:26:33 +00:00
Readme.txt Fixed bugs in TypeTraits' scalar, array, const and volatile detection. 2003-01-31 20:13:57 +00:00
Singleton.cpp Benjamin Kaufmann's port 2003-01-06 02:26:33 +00:00
Singleton.h changed SingletonHolder::MakeInstance in accordance with Bug-report #691687 2003-02-27 15:51:25 +00:00
SmallObj.cpp Benjamin Kaufmann's port 2003-01-06 02:26:33 +00:00
SmallObj.h Small fix to operator new 2003-01-25 12:56:30 +00:00
SmartPtr.h ported RefCountedMT. Corrected NoCopy 2003-02-27 15:50:55 +00:00
static_check.h Benjamin Kaufmann's port 2003-01-06 02:26:33 +00:00
Threads.h corrected constructor parameter in ObjectLevelLockable::Lock 2003-02-27 15:50:07 +00:00
Tuple.h Benjamin Kaufmann's port 2003-01-06 02:26:33 +00:00
TypeInfo.h Benjamin Kaufmann's port 2003-01-06 02:26:33 +00:00
Typelist.h fixed bug in DerivedToFront. Renamed MakeTypeList -> MakeTypelist 2003-02-27 15:49:36 +00:00
TypeManip.h Benjamin Kaufmann's port 2003-01-10 01:33:21 +00:00
TypeTraits.h added isFunctionPointer and restructured code 2003-02-27 15:48:45 +00:00
Visitor.h new version better supports return type void 2003-02-27 15:47:47 +00:00

Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors
-------------------------------------------------------------------
Version: 0.3b

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
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
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
Hume@c-plusplus.de

Using this port:
----------------
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)
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:
------

	Jan 30, 2003:
	-------------
		* In TypeTraits.h: Fixed bugs in TypeTraits' scalar and array detection.
		const and volatile detection is now based on techniques from boost's type traits
		(see http://www.boost.org/libs/type_traits/)
		Added Enum- and pointer-to-member-function-detection code.
		Thanks to M. Yamada.


	Jan 12, 2003:
	-------------
		* changed the signature of SmallObject's op new. Now it
		matches the corresponding op delete.
		Thanks to M.Yamada for the hint and the solution.

	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:
------
The original Loki Lib uses some pretty advanced (resp. new) C++ features like:

A. partial template specialization.
B. template template parameters.
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.

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
	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.
	The problem with this approach is MSVC's 'dependent template typedef bug'. MSVC 6.0 does not
	allow something like this:

	[code]
	template <class APolicy, class T>
	struct Foo
	{
		// '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
	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.

	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]
	struct Foo
	{
		template <class T>
		T Func();
	};
	[/code]
	becomes
	[code]
	struct Foo
	{
		template <class T>
		T Func(T* pDummy1);
	};
	[/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 (an udt). This change is
	transparent to 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 :-(

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)
	{}

	Foo(const Foo& r)
	{}
};
[/code]

Many thanks to Nelson El<45>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<45>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'.

	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.

	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
	type and  ThreadingModel its current ThreadingModel.

4. TypeTraits.h

	*	Because VC 6.0 lacks partial template specialization, the TypeTraits-Class
	fails to provide the following typedefs:
	PointeeType, ReferredType, NonVolatileType and UnqualifiedType.

	*	Since the VC 6 does not differentiate
	between void, const void, volatile void and const volatile void the following
	assertions will fail:
	assert(TypeTraits<const void>::isConst == 1)
	assert(TypeTraits<volatile void>::isVolatile == 1)
	assert(TypeTraits<const volatile void>::isConst == 1)
	assert(TypeTraits<const volatile void>::isVolatile == 1)

	*	This port adds isEnum and isMemberFuncPointer


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.

	consequences:
	This change will only break new Policies when switching to the
	original library.

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
	concrete Factory-Unit.

	*	Added a dummy-Parameter to AbstractFactory::Create (see C.)
	Calling syntax changed from:
		ConcProduct* p = aFactory.Create<ConcProduct>();
	to
		ConcProduct* p = aFactory.Create((ConcProduct*)0);


8. SmartPtr.h

   * no template template parameters.
   (see 7.for a description of the consequences)

   * This port does not specialize std::less

9. Visitor.h

	* 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
	a set of complete new classes (and macros) for void. Default arguments of type void
	were replaced by arguments of type int.


10. MultiMethods.h

	* replaced all template template parameters with 'normal' parameters (see 7.
	for a description of the consequences)

	* This port does not support functions with return type void.

	* dummy parameters were added to functions that otherwise would depend on
	explicit template argument specification (14.8.1).


More info:
----------
The original Loki library can be found here: http://moderncppdesign.com
For Rani Sharoni's VC 7.0 port see: http://www.geocities.com/rani_sharoni/LokiPort.html