/*
								+----------------------------------+
								|                                  |
								|        ***  Typelist  ***        |
								|                                  |
								|   Copyright © -tHE SWINe- 2014   |
								|                                  |
								|            Typelist.h            |
								|                                  |
								+----------------------------------+
*/

#pragma once
#ifndef __TYPELIST_LIBRARY_INCLUDED
#define __TYPELIST_LIBRARY_INCLUDED

/**
 *	@file Typelist.h
 *	@brief typelist template and operations
 *	@author -tHE SWINe-
 *	@date 2014-02-10
 */

#include <stdio.h> // have print utils here, need printf()
#include "Unused.h"

#if defined(_MSC_VER) && !defined(__MWERKS__)
#pragma warning(disable: 4786)
#pragma warning(disable: 4503)
#endif // _MSC_VER && !__MWERKS__
// disable MSVC warnings "identifier was truncated to '255' characters in the browser information"
// and "decorated name length exceeded, name was truncated"

/**
 *	@brief type pair template
 *
 *	@tparam TFirst is the first type
 *	@tparam TSecond is the second type
 *
 *	@note This is not supposed to be a recursive structure, just a simple pair of types.
 */
template <class TFirst, class TSecond>
struct CTypePair {
	typedef TFirst CFirst; /**< @brief the first type */
	typedef TSecond CSecond; /**< @brief the second type */
};

/**
 *	@brief typelist template
 *
 *	@tparam THead is head type
 *	@tparam TTail is tail type (another CTypelist or CTypelistEnd)
 *
 *	@note An empty typelist is represented by CTypelistEnd, not by CTypelist<CTypelistEnd, CTypelistEnd>.
 */
template <class THead, class TTail>
struct CTypelist {
	typedef THead CHead; /**< @brief head type */
	typedef TTail CTail; /**< @brief tail type (another CTypelist or CTypelistEnd) */
};

/**
 *	@brief typelist end marker type, also an empty typelist all by itself
 */
struct CTypelistEnd {};

/**
 *	@brief typelist assertion container template
 *	@tparam b_value is asserted value (must be a compile-time constant)
 */
template <const bool b_value>
struct CTypelistAssert {};

/**
 *	@brief typelist assertion container template (specialization for assertion passed)
 */
template <>
struct CTypelistAssert<true> {
	typedef void INDEX_OUT_OF_BOUNDS; /**< @brief assertion tag for typelist lookup */
	typedef void TYPELISTS_MUST_BE_OF_THE_SAME_LENGTH; /**< @brief assertion tag for transform on a pair of typelists */
	typedef void TYPELIST_MUST_BE_NON_EMPTY; /**< @brief assertion tag for decision tree from a typelist */
	typedef void SIZE_OF_THE_SEQUENCE_MUST_BE_NONNEGATIVE; /**< @brief assertion tag for sequence generation */
};

/**
 *	@def MakeTypelist1
 *	@brief makes a typelist with 1 item
 *
 *	@param[in] A is a typelist item
 */
#define MakeTypelist1(A) CTypelist<A, CTypelistEnd>

/**
 *	@def MakeTypelist2
 *	@brief makes a typelist with 2 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 */
#define MakeTypelist2(A,B) CTypelist<A, MakeTypelist1(B) >

/**
 *	@def MakeTypelist3
 *	@brief makes a typelist with 3 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 */
#define MakeTypelist3(A,B,C) CTypelist<A, MakeTypelist2(B, C) >

/**
 *	@def MakeTypelist4
 *	@brief makes a typelist with 4 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 */
#define MakeTypelist4(A,B,C,D) CTypelist<A, MakeTypelist3(B, C, D) >

/**
 *	@def MakeTypelist5
 *	@brief makes a typelist with 5 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 */
#define MakeTypelist5(A,B,C,D,E) CTypelist<A, MakeTypelist4(B, C, D, E) >

/**
 *	@def MakeTypelist6
 *	@brief makes a typelist with 6 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 */
#define MakeTypelist6(A,B,C,D,E,F) CTypelist<A, MakeTypelist5(B, C, D, E, F) >

/**
 *	@def MakeTypelist7
 *	@brief makes a typelist with 7 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 */
#define MakeTypelist7(A,B,C,D,E,F,G) CTypelist<A, MakeTypelist6(B, C, D, E, \
	F, G) >

/**
 *	@def MakeTypelist8
 *	@brief makes a typelist with 8 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 */
#define MakeTypelist8(A,B,C,D,E,F,G,H) CTypelist<A, MakeTypelist7(B, C, D, E, \
	F, G, H) >

/**
 *	@def MakeTypelist9
 *	@brief makes a typelist with 9 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 */
#define MakeTypelist9(A,B,C,D,E,F,G,H,I) CTypelist<A, MakeTypelist8(B, C, D, \
	E, F, G, H, I) >

/**
 *	@def MakeTypelist10
 *	@brief makes a typelist with 10 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 */
#define MakeTypelist10(A,B,C,D,E,F,G,H,I,J) CTypelist<A, MakeTypelist9(B, C, \
	D, E, F, G, H, I, J) >

/**
 *	@def MakeTypelist11
 *	@brief makes a typelist with 11 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 */
#define MakeTypelist11(A,B,C,D,E,F,G,H,I,J,K) CTypelist<A, MakeTypelist10(B, \
	C, D, E, F, G, H, I, J, K) >

/**
 *	@def MakeTypelist12
 *	@brief makes a typelist with 12 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 */
#define MakeTypelist12(A,B,C,D,E,F,G,H,I,J,K,L) CTypelist<A, MakeTypelist11(B, \
	C, D, E, F, G, H, I, J, K, L) >

/**
 *	@def MakeTypelist13
 *	@brief makes a typelist with 13 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 */
#define MakeTypelist13(A,B,C,D,E,F,G,H,I,J,K,L,M) \
	CTypelist<A, MakeTypelist12(B, C, D, E, F, G, H, I, J, K, L, M) >

/**
 *	@def MakeTypelist14
 *	@brief makes a typelist with 14 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 */
#define MakeTypelist14(A,B,C,D,E,F,G,H,I,J,K,L,M,N) \
	CTypelist<A, MakeTypelist13(B, C, D, E, F, G, H, I, J, K, L, M, N) >

/**
 *	@def MakeTypelist15
 *	@brief makes a typelist with 15 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 */
#define MakeTypelist15(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O) \
	CTypelist<A, MakeTypelist14(B, C, D, E, F, G, H, I, J, K, L, M, N, O) >

/**
 *	@def MakeTypelist16
 *	@brief makes a typelist with 16 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 */
#define MakeTypelist16(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P) \
	CTypelist<A, MakeTypelist15(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) >

/**
 *	@def MakeTypelist17
 *	@brief makes a typelist with 17 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 */
#define MakeTypelist17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q) \
	CTypelist<A, MakeTypelist16(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) >

/**
 *	@def MakeTypelist18
 *	@brief makes a typelist with 18 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 */
#define MakeTypelist18(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) \
	CTypelist<A, MakeTypelist17(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R) >

/**
 *	@def MakeTypelist19
 *	@brief makes a typelist with 19 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 */
#define MakeTypelist19(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S) \
	CTypelist<A, MakeTypelist18(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R, S) >

/**
 *	@def MakeTypelist20
 *	@brief makes a typelist with 20 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 */
#define MakeTypelist20(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T) \
	CTypelist<A, MakeTypelist19(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R, S, T) >

/**
 *	@def MakeTypelist21
 *	@brief makes a typelist with 21 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 */
#define MakeTypelist21(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U) \
	CTypelist<A, MakeTypelist20(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R, S, T, U) >

/**
 *	@def MakeTypelist22
 *	@brief makes a typelist with 22 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 */
#define MakeTypelist22(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V) \
	CTypelist<A, MakeTypelist21(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R, S, T, U, V) >

/**
 *	@def MakeTypelist23
 *	@brief makes a typelist with 23 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 */
#define MakeTypelist23(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W) \
	CTypelist<A, MakeTypelist22(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R, S, T, U, V, W) >

/**
 *	@def MakeTypelist24
 *	@brief makes a typelist with 24 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 *	@param[in] X is a typelist item
 */
#define MakeTypelist24(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X) \
	CTypelist<A, MakeTypelist23(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R, S, T, U, V, W, X) >

/**
 *	@def MakeTypelist25
 *	@brief makes a typelist with 25 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 *	@param[in] X is a typelist item
 *	@param[in] Y is a typelist item
 */
#define MakeTypelist25(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y) \
	CTypelist<A, MakeTypelist24(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R, S, T, U, V, W, X, Y) >

/**
 *	@def MakeTypelist26
 *	@brief makes a typelist with 26 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 *	@param[in] X is a typelist item
 *	@param[in] Y is a typelist item
 *	@param[in] Z is a typelist item
 */
#define MakeTypelist26(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) \
	CTypelist<A, MakeTypelist25(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R, S, T, U, V, W, X, Y, Z) >

/**
 *	@def MakeTypelist27
 *	@brief makes a typelist with 27 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 *	@param[in] X is a typelist item
 *	@param[in] Y is a typelist item
 *	@param[in] Z is a typelist item
 *	@param[in] a is a typelist item
 */
#define MakeTypelist27(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a) \
	CTypelist<A, MakeTypelist26(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, \
	R, S, T, U, V, W, X, Y, Z, a) >

/**
 *	@def MakeTypelist28
 *	@brief makes a typelist with 28 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 *	@param[in] X is a typelist item
 *	@param[in] Y is a typelist item
 *	@param[in] Z is a typelist item
 *	@param[in] a is a typelist item
 *	@param[in] b is a typelist item
 */
#define MakeTypelist28(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a, \
	b) CTypelist<A, MakeTypelist27(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, \
	Q, R, S, T, U, V, W, X, Y, Z, a, b) >

/**
 *	@def MakeTypelist29
 *	@brief makes a typelist with 29 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 *	@param[in] X is a typelist item
 *	@param[in] Y is a typelist item
 *	@param[in] Z is a typelist item
 *	@param[in] a is a typelist item
 *	@param[in] b is a typelist item
 *	@param[in] c is a typelist item
 */
#define MakeTypelist29(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a, \
	b,c) CTypelist<A, MakeTypelist28(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, \
	Q, R, S, T, U, V, W, X, Y, Z, a, b, c) >

/**
 *	@def MakeTypelist30
 *	@brief makes a typelist with 30 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 *	@param[in] X is a typelist item
 *	@param[in] Y is a typelist item
 *	@param[in] Z is a typelist item
 *	@param[in] a is a typelist item
 *	@param[in] b is a typelist item
 *	@param[in] c is a typelist item
 *	@param[in] d is a typelist item
 */
#define MakeTypelist30(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a, \
	b,c,d) CTypelist<A, MakeTypelist29(B, C, D, E, F, G, H, I, J, K, L, M, N, O, \
	P, Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d) >

/**
 *	@def MakeTypelist31
 *	@brief makes a typelist with 31 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 *	@param[in] X is a typelist item
 *	@param[in] Y is a typelist item
 *	@param[in] Z is a typelist item
 *	@param[in] a is a typelist item
 *	@param[in] b is a typelist item
 *	@param[in] c is a typelist item
 *	@param[in] d is a typelist item
 *	@param[in] e is a typelist item
 */
#define MakeTypelist31(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a, \
	b,c,d,e) CTypelist<A, MakeTypelist30(B, C, D, E, F, G, H, I, J, K, L, M, N, \
	O, P, Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e) >

/**
 *	@def MakeTypelist32
 *	@brief makes a typelist with 32 items
 *
 *	@param[in] A is a typelist item
 *	@param[in] B is a typelist item
 *	@param[in] C is a typelist item
 *	@param[in] D is a typelist item
 *	@param[in] E is a typelist item
 *	@param[in] F is a typelist item
 *	@param[in] G is a typelist item
 *	@param[in] H is a typelist item
 *	@param[in] I is a typelist item
 *	@param[in] J is a typelist item
 *	@param[in] K is a typelist item
 *	@param[in] L is a typelist item
 *	@param[in] M is a typelist item
 *	@param[in] N is a typelist item
 *	@param[in] O is a typelist item
 *	@param[in] P is a typelist item
 *	@param[in] Q is a typelist item
 *	@param[in] R is a typelist item
 *	@param[in] S is a typelist item
 *	@param[in] T is a typelist item
 *	@param[in] U is a typelist item
 *	@param[in] V is a typelist item
 *	@param[in] W is a typelist item
 *	@param[in] X is a typelist item
 *	@param[in] Y is a typelist item
 *	@param[in] Z is a typelist item
 *	@param[in] a is a typelist item
 *	@param[in] b is a typelist item
 *	@param[in] c is a typelist item
 *	@param[in] d is a typelist item
 *	@param[in] e is a typelist item
 *	@param[in] f is a typelist item
 */
#define MakeTypelist32(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a, \
	b,c,d,e,f) CTypelist<A, MakeTypelist31(B, C, D, E, F, G, H, I, J, K, L, M, N, \
	O, P, Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e, f) >
// mind the space at the end, that is significant in there!

#if !defined(_MSC_VER) || defined(__MWERKS__) || _MSC_VER >= 1400

/**
 *	@brief safe typelist constructor
 *	@tparam TyFunction is a function pointer type (unrelated to typelist contents,
 *		merely a mechanism of resolving the types themselves using partial specialization)
 *	@note This is not available in MSVC60.
 */
template <class TyFunction>
struct CSafeTypelistCtor;

/**
 *	@brief makes a typelist with 1 item
 *	@tparam A is a typelist item
 *	@note This is not available in MSVC60.
 */
template <class A>
struct CSafeTypelistCtor<void (*)(A)> {
	typedef MakeTypelist1(A) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 2 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B>
struct CSafeTypelistCtor<void (*)(A, B)> {
	typedef MakeTypelist2(A, B) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 3 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C>
struct CSafeTypelistCtor<void (*)(A, B, C)> {
	typedef MakeTypelist3(A, B, C) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 4 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D>
struct CSafeTypelistCtor<void (*)(A, B, C, D)> {
	typedef MakeTypelist4(A, B, C, D) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 5 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E)> {
	typedef MakeTypelist5(A, B, C, D, E) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 6 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F)> {
	typedef MakeTypelist6(A, B, C, D, E,
		F) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 7 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G)> {
	typedef MakeTypelist7(A, B, C, D, E, F,
		G) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 8 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H)> {
	typedef MakeTypelist8(A, B, C, D, E, F, G,
		H) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 9 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I)> {
	typedef MakeTypelist9(A, B, C, D, E, F, G, H,
		I) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 10 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J)> {
	typedef MakeTypelist10(A, B, C, D, E, F, G, H, I,
		J) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 11 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K)> {
	typedef MakeTypelist11(A, B, C, D, E, F, G, H, I, J,
		K) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 12 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L)> {
	typedef MakeTypelist12(A, B, C, D, E, F, G, H, I, J, K,
		L) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 13 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M)> {
	typedef MakeTypelist13(A, B, C, D, E, F, G, H, I, J, K, L,
		M) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 14 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N)> {
	typedef MakeTypelist14(A, B, C, D, E, F, G, H, I, J, K, L, M,
		N) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 15 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)> {
	typedef MakeTypelist15(A, B, C, D, E, F, G, H, I, J, K, L, M, N,
		O) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 16 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P)> {
	typedef MakeTypelist16(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O,
		P) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 17 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q)> {
	typedef MakeTypelist17(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
		Q) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 18 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R)> {
	typedef MakeTypelist18(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,
		R) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 19 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S)> {
	typedef MakeTypelist19(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R,
		S) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 20 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T)> {
	typedef MakeTypelist20(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 21 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U)> {
	typedef MakeTypelist21(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 22 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V)> {
	typedef MakeTypelist22(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 23 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W)> {
	typedef MakeTypelist23(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 24 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *	@tparam X is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W, class X>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W, X)> {
	typedef MakeTypelist24(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W, X) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 25 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *	@tparam X is a typelist item
 *	@tparam Y is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W, class X, class Y>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W, X, Y)> {
	typedef MakeTypelist25(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W, X, Y) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 26 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *	@tparam X is a typelist item
 *	@tparam Y is a typelist item
 *	@tparam Z is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W, class X, class Y, class Z>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W, X, Y, Z)> {
	typedef MakeTypelist26(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W, X, Y, Z) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 27 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *	@tparam X is a typelist item
 *	@tparam Y is a typelist item
 *	@tparam Z is a typelist item
 *	@tparam a is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W, class X, class Y, class Z,
	class a>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W, X, Y, Z, a)> {
	typedef MakeTypelist27(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W, X, Y, Z, a) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 28 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *	@tparam X is a typelist item
 *	@tparam Y is a typelist item
 *	@tparam Z is a typelist item
 *	@tparam a is a typelist item
 *	@tparam b is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W, class X, class Y, class Z,
	class a, class b>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W, X, Y, Z, a, b)> {
	typedef MakeTypelist28(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W, X, Y, Z, a, b) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 29 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *	@tparam X is a typelist item
 *	@tparam Y is a typelist item
 *	@tparam Z is a typelist item
 *	@tparam a is a typelist item
 *	@tparam b is a typelist item
 *	@tparam c is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W, class X, class Y, class Z,
	class a, class b, class c>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W, X, Y, Z, a, b, c)> {
	typedef MakeTypelist29(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W, X, Y, Z, a, b, c) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 30 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *	@tparam X is a typelist item
 *	@tparam Y is a typelist item
 *	@tparam Z is a typelist item
 *	@tparam a is a typelist item
 *	@tparam b is a typelist item
 *	@tparam c is a typelist item
 *	@tparam d is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W, class X, class Y, class Z,
	class a, class b, class c, class d>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d)> {
	typedef MakeTypelist30(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W, X, Y, Z, a, b, c,
		d) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 31 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *	@tparam X is a typelist item
 *	@tparam Y is a typelist item
 *	@tparam Z is a typelist item
 *	@tparam a is a typelist item
 *	@tparam b is a typelist item
 *	@tparam c is a typelist item
 *	@tparam d is a typelist item
 *	@tparam e is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W, class X, class Y, class Z,
	class a, class b, class c, class d, class e>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e)> {
	typedef MakeTypelist31(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W, X, Y, Z, a, b, c, d,
		e) CResult; /**< @brief resulting typelist */
};

/**
 *	@brief makes a typelist with 32 items
 *
 *	@tparam A is a typelist item
 *	@tparam B is a typelist item
 *	@tparam C is a typelist item
 *	@tparam D is a typelist item
 *	@tparam E is a typelist item
 *	@tparam F is a typelist item
 *	@tparam G is a typelist item
 *	@tparam H is a typelist item
 *	@tparam I is a typelist item
 *	@tparam J is a typelist item
 *	@tparam K is a typelist item
 *	@tparam L is a typelist item
 *	@tparam M is a typelist item
 *	@tparam N is a typelist item
 *	@tparam O is a typelist item
 *	@tparam P is a typelist item
 *	@tparam Q is a typelist item
 *	@tparam R is a typelist item
 *	@tparam S is a typelist item
 *	@tparam T is a typelist item
 *	@tparam U is a typelist item
 *	@tparam V is a typelist item
 *	@tparam W is a typelist item
 *	@tparam X is a typelist item
 *	@tparam Y is a typelist item
 *	@tparam Z is a typelist item
 *	@tparam a is a typelist item
 *	@tparam b is a typelist item
 *	@tparam c is a typelist item
 *	@tparam d is a typelist item
 *	@tparam e is a typelist item
 *	@tparam f is a typelist item
 *
 *	@note This is not available in MSVC60.
 */
template <class A, class B, class C, class D, class E, class F, class G, class H,
	class I, class J, class K, class L, class M, class N, class O, class P, class Q,
	class R, class S, class T, class U, class V, class W, class X, class Y, class Z,
	class a, class b, class c, class d, class e, class f>
struct CSafeTypelistCtor<void (*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P,
	Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e, f)> {
	typedef MakeTypelist32(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S,
		T, U, V, W, X, Y, Z, a, b, c, d, e,
		f) CResult; /**< @brief resulting typelist */
};

/**
 *	@def MakeTypelist
 *
 *	@brief makes a typelist (version with variable number of arguments)
 *
 *	@param[in] ... is the list of items of typelist
 *
 *	@return Returns declaration of a typelist containing all the entered types, in the given order.
 *
 *	@note This only compiles on compilers, supporting variadic macros.
 *	@note This is not available in MSVC60.
 */
#define MakeTypelist(...) CSafeTypelistCtor<void (*)(__VA_ARGS__)>::CResult

/**
 *	@def MakeTypelist_Safe
 *
 *	@brief makes a typelist (version with variable number of arguments)
 *
 *	@param[in] args is the list of items of typelist
 *
 *	@return Returns declaration of a typelist containing all the entered types, in the given order.
 *
 *	@note This is used with double parentheses, e.g. MakeTypelist_Safe((char, short, int)).
 *	@note This is not available in MSVC60.
 */
#define MakeTypelist_Safe(args) CSafeTypelistCtor<void (*)args>::CResult

#endif // !_MSC_VER || __MWERKS__ || _MSC_VER >= 1400

/**
 *	@brief compile-time boolean flag
 *	@tparam _b_flag is flag value
 *	@note This can be used to store bit array in a typelist.
 */
template <const bool _b_flag>
struct CCTFlag {
	/**
	 *	@brief value, stored as enum
	 */
	enum {
		b_flag = _b_flag /**< @brief flag value */
	};

	/**
	 *	@brief less-than comparison operator
	 *	@tparam COther is other specialization of the CCTFlag template
	 */
	template <class COther>
	struct CCompare {
		/**
		 *	@brief comparison result, stored as enum
		 */
		enum {
			b_result = int(b_flag) == 0 && int(COther::b_flag) != 0 /**< @brief comparison result (true if this < COther) */
		};
	};
};

/**
 *	@brief compile-time scalar (integer) size
 *	@tparam _n_size is size
 *	@note This can be used to store integer array in a typelist.
 */
template <const int _n_size>
struct CCTSize {
	/**
	 *	@brief value, stored as enum
	 */
	enum {
		n_size = _n_size /**< @brief scalar value */
	};

	/**
	 *	@brief less-than comparison operator
	 *	@tparam COther is other specialization of the CCTSize template
	 */
	template <class COther>
	struct CCompare {
		/**
		 *	@brief comparison result, stored as enum
		 */
		enum {
			b_result = int(n_size) < int(COther::n_size) /**< @brief comparison result (true if this < COther) */
		};
	};
};

/**
 *	@brief compile-time 2D (integer) size
 *
 *	@tparam _n_width is width
 *	@tparam _n_height is height
 *
 *	@note This can be used to store 2D size array in a typelist.
 */
template <const int _n_width, const int _n_height>
struct CCTSize2D {
	/**
	 *	@brief values, stored as enum
	 */
	enum {
		n_width = _n_width, /**< @brief value of width */
		n_height = _n_height /**< @brief value of height */
	};

	/**
	 *	@brief less-than comparison operator
	 *	@tparam COther is other specialization of the CCTSize2D template
	 */
	template <class COther>
	struct CCompare {
		/**
		 *	@brief comparison result, stored as enum
		 */
		enum {
			b_result = int(n_width) < int(COther::n_width) ||
				(int(n_width) == int(COther::n_width) &&
				int(n_height) < int(COther::n_height)) /**< @brief comparison result (true if this < COther) */
		};
	};
};

/**
 *	@def MSVC_OMMIT
 *	@param[in] x is a declaration / statement
 *	@brief ommits the argument when compiled on MSVC, otherwise resolves to the argument
 */
/**
 *	@def MSVC_OMMIT_ARG
 *	@param[in] x is a declaration / statement
 *	@brief ommits the argument when compiled on MSVC, otherwise resolves to a comma,followed by the argument
 */
#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(MSVC_OMMIT)
#define MSVC_OMMIT(x) 
#define MSVC_OMMIT_ARG(x) 
#elif !defined(MSVC_OMMIT) // _MSC_VER && !__MWERKS__ && !MSVC_OMMIT
#define MSVC_OMMIT(x) x
#define MSVC_OMMIT_ARG(x) , x
#endif // _MSC_VER && !__MWERKS__ && !MSVC_OMMIT

/**
 *	@def MSVC6_OMMIT
 *	@param[in] x is a declaration / statement
 *	@brief ommits the argument when compiled on MSVC, otherwise resolves to the argument
 */
/**
 *	@def MSVC6_OMMIT_ARG
 *	@param[in] x is a declaration / statement
 *	@brief ommits the argument when compiled on MSVC, otherwise resolves to a comma,followed by the argument
 */
#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER <= 1200 && !defined(MSVC6_OMMIT)
#define MSVC6_OMMIT(x) 
#define MSVC6_OMMIT_ARG(x) 
#elif !defined(MSVC6_OMMIT) // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200 && !MSVC6_OMMIT
#define MSVC6_OMMIT(x) x
#define MSVC6_OMMIT_ARG(x) , x
#endif // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200 && !MSVC6_OMMIT

/**
 *	@def IS_OMMIT
 *	@param[in] x is a declaration / statement
 *	@brief ommits the argument when compiled on compilers
 *		with intellisense support, otherwise resolves to the argument
 */
#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(IS_OMMIT)
#define IS_OMMIT(x) 
#elif !defined(IS_OMMIT) // _MSC_VER && !__MWERKS__ && !IS_OMMIT
#define IS_OMMIT(x) x
#endif // _MSC_VER && !__MWERKS__ && !IS_OMMIT

/**
 *	@brief calculates length of typelist (result in member enum n_result)
 *	@tparam CList is a typelist
 */
template <class CList>
struct CTypelistLength {
	/**
	 *	@brief intermediates, stored as enum
	 */
	enum {
		n_result = 1 + CTypelistLength<typename CList::CTail>::n_result /**< @brief length of the list (the result) */
	};
};

/**
 *	@brief calculates length of typelist (specialization for empty list
 *		(end of the list); result in member enum n_result)
 */
template <>
struct CTypelistLength<CTypelistEnd> {
	/**
	 *	@brief intermediates, stored as enum
	 */
	enum {
		n_result = 0 /**< @brief length of the list (the result) */
	};
};

/**
 *	@brief namespace with msvc 6.0 specific workarrounds
 */
namespace tl_msvc6 {

/**
 *	@brief type comparison environment (msvc partial specialization issue workarround)
 *	@tparam A is the first type to compared
 */
template <class A>
struct CCompareType {
	/**
	 *	@brief type comparison template
	 *
	 *	@tparam B is the second type to be compared
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class B MSVC_OMMIT_ARG(class GppDummy)>
	struct CCompare {
		/**
		 *	@brief result, stored as enum
		 */
		enum {
			b_result = false /**< @brief comparison result */
		};
	};

	/**
	 *	@brief type comparison template (specialization for the types being equal)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CCompare<A MSVC_OMMIT_ARG(GppDummy)> {
		/**
		 *	@brief result, stored as enum
		 */
		enum {
			b_result = true /**< @brief comparison result */
		};
	};
};

/**
 *	@brief typelist lookup environment (msvc partial specialization issue workarround)
 *	@tparam CList is typelist
 */
template <class CList>
struct CTypelistLookup {
	/**
	 *	@brief item selection template
	 *
	 *	@tparam n_offset is zero-based index of the item to be selected
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <const int n_offset MSVC_OMMIT_ARG(class GppDummy)>
	struct CSelectItem {
		typedef typename CTypelistLookup<typename CList::CTail>::IS_OMMIT(template) CSelectItem<n_offset - 1
			MSVC_OMMIT_ARG(GppDummy)>::CResult CResult; /**< @brief type of the selected item */
	};

	/**
	 *	@brief item selection template (specialization for index zero)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CSelectItem<0 MSVC_OMMIT_ARG(GppDummy)> {
		typedef typename CList::CHead CResult; /**< @brief type of the selected item */
	};
};

/**
 *	@brief typelist lookup environment (msvc partial specialization issue
 *		workarround; specialization for an empty typelist or typelist end)
 *	@tparam CList is typelist
 */
template <>
struct CTypelistLookup<CTypelistEnd> {
	/**
	 *	@brief item selection template
	 *
	 *	@tparam n_offset is zero-based index of the item to be selected
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <const int n_offset MSVC_OMMIT_ARG(class GppDummy)>
	struct CSelectItem {
		typedef typename CTypelistAssert<(n_offset != n_offset)>::INDEX_OUT_OF_BOUNDS CIndexAssert; /**< @brief the index is out of bounds in this case */
		// involving n_offset in the expression does not trigger the exception during syntax analysis in msvc

		typedef CTypelistEnd CResult; /**< @brief type of the selected item */
	};
};

} // ~tl_msvc6

/**
 *	@brief template for comparing two data types
 *
 *	@tparam TA is the first type
 *	@tparam TB is the second type
 */
template <class TA, class TB>
struct CIsSameType {
	/**
	 *	@brief result, stored as enum
	 */
	enum {
		b_result = tl_msvc6::CCompareType<TA>::IS_OMMIT(template)
			CCompare<TB MSVC_OMMIT_ARG(void)>::b_result /**< @brief result of comparison (the types are different) */
	};
};

/**
 *	@brief picks a typelist item, selected by an index
 *
 *	@tparam CList is a typelist
 *	@tparam n_index is a zero-based index of an item to be returned
 *
 *	@note This handles out-of-bounds array access by triggering the INDEX_OUT_OF_BOUNDS assertion.
 */
template <class CList, const int n_index>
class CTypelistItemAt {
protected:
	enum { b_in_bounds = n_index >= 0/* && n_index < CTypelistLength<CList>::n_result*/ };
	typedef typename CTypelistAssert<b_in_bounds>::INDEX_OUT_OF_BOUNDS CIndexAssert; /**< @brief index out of bounds assertion */
	// calculating length is unnecessarily expensive, the other bound is checked by tl_msvc6::CTypelistLookup

public:
	typedef typename tl_msvc6::CTypelistLookup<CList>::IS_OMMIT(template)
		CSelectItem<n_index MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief type of the selected item */
};

namespace tl_msvc6 {

/**
 *	@brief typelist search environment (msvc partial specialization issue workarround)
 *	@tparam CRef is reference type to be found
 */
template <class CRef>
struct CTypelistSearch {
	/**
	 *	@brief compares list items to the reference type
	 *
	 *	@tparam CList is the list
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class CList MSVC_OMMIT_ARG(class GppDummy)>
	struct CFind {
		typedef CFind<typename CList::CTail MSVC_OMMIT_ARG(GppDummy)> CRecurse; /**< @brief recursive search on the rest of the list */

		/**
		 *	@brief result, stored as enum
		 */
		enum {
			b_found_here = CIsSameType<typename CList::CHead, CRef>::b_result, /**< @brief item found here flag */

			b_found = b_found_here || CRecurse::b_found, /**< @brief item found in the list flag */
			n_index = (b_found_here)? 0 : (b_found)? CRecurse::n_index + 1 : -1 /**< @brief item index in the list */
		};
	};

	/**
	 *	@brief compares list items to the reference type (specialization for the end of the list, or an empty list)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CFind<CTypelistEnd MSVC_OMMIT_ARG(GppDummy)> {
		/**
		 *	@brief result, stored as enum
		 */
		enum {
			b_found = false, /**< @brief item found in the list flag */
			n_index = -1 /**< @brief item index in the list */
		};
	};
};

/**
 *	@brief helper environment for typelist split
 *	@tparam CList is input typelist
 */
template <class CList>
class CTypelistSplitEnv {
public:
	/**
	 *	@brief splits a typelist to two halves
	 *
	 *	@tparam n_split is index of the split
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <const int n_split MSVC_OMMIT_ARG(class GppDummy)>
	class CSplit {
	protected:
		typedef typename CList::CHead H; /**< @brief list head */
		typedef typename CList::CTail T; /**< @brief list tail */
		typedef CTypelistSplitEnv<typename CList::CTail> CEnv; /**< @brief tail split environment */

	public:
		typedef CTypelist<H, typename CEnv::CSplit<n_split - 1>::CFirst> CFirst; /**< @brief the first half of the split */
		typedef typename CEnv::CSplit<n_split - 1>::CSecond CSecond; /**< @brief the second half of the split */
	};

	/**
	 *	@brief splits a typelist to two halves (specialization for split at the beginning)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	class CSplit<0 MSVC_OMMIT_ARG(GppDummy)>  {
	public:
		typedef CTypelistEnd CFirst; /**< @brief the first half of the split */
		typedef CList CSecond; /**< @brief the second half of the split */
	};
};

} // ~tl_msvc6

/**
 *	@brief splits a typelist in two halves
 *
 *	@tparam CList is input typelist
 *	@tparam n_split is length of the first half of the split (must be
 *		nonnegative and less or equal to the list length)
 */
template <class CList, const int n_split>
class CSplitTypelist {
protected:
	typedef tl_msvc6::CTypelistSplitEnv<CList> CEnv; /**< @brief split environment */
	typedef typename CEnv::CSplit<n_split> CSplit; /**< @brief split environment */

public:
	/**
	 *	@brief intermediates, stored as enum
	 */
	enum {
		n_length = CTypelistLength<CList>::n_result, /**< @brief length of the list */
		b_valid_index = n_split >= 0 && n_split <= n_length /**< @brief result of bounds check on the split index */
	};

	typedef typename CTypelistAssert<b_valid_index>::INDEX_OUT_OF_BOUNDS CAssert; /**< @brief makes sure that the split is not out of bounds (otherwise will get strange errors about template recursion) */

	typedef typename CSplit::CFirst CFirst; /**< @brief the first half of the split */
	typedef typename CSplit::CSecond CSecond; /**< @brief the second half of the split */
};

/**
 *	@brief gets a span of a typelist
 *
 *	@tparam CList is input typelist
 *	@tparam n_begin is zero-based index of the first item in the resulting list
 *	@tparam n_end is zero-based index of one past the last item in the resulting list
 */
template <class CList, const int n_begin, const int n_end>
class CTypelistSpan {
public:
	typedef typename CSplitTypelist<typename CSplitTypelist<CList, n_begin>::CSecond,
		n_end - n_begin>::CFirst CResult; /**< @brief the result */
	// this first cuts begin and then end, it takes O(n_begin) + O(n_end - n_begin) of recursions
	// the other split order would be O(n_end) + O(n_begin) which is clearly more costly
};

/**
 *	@brief finds type in a typelist
 *
 *	@tparam CList is typelist type
 *	@tparam CRef is type of the item being searched
 */
template <class CList, class CRef>
class CFindTypelistItem {
protected:
	typedef typename tl_msvc6::CTypelistSearch<CRef>::IS_OMMIT(template)
		CFind<CList MSVC_OMMIT_ARG(void)> CImpl; /**< @brief search implementation */

public:
	enum {
		b_found = CImpl::b_found, /**< @brief item found in the list flag */
		n_index = CImpl::n_index /**< @brief item index in the list (or -1 if not found) */
	};
};

/**
 *	@brief chooses one of two types, based on a compile-time flag
 *
 *	@tparam CFirst is the first type
 *	@tparam CSecond is the second type
 *	@tparam b_choose_first is flag that chooses the first (true) or the second (false) type
 */
template <class CFirst, class CSecond, bool b_choose_first>
class CChooseType {
protected:
	/**
	 *	@brief compares the flag (msvc partial specialization issue workarround)
	 *
	 *	@tparam b_first is flag that chooses the first (true) or the second (false) type
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <const bool b_first MSVC_OMMIT_ARG(class GppDummy)>
	struct CChoose {
		typedef CFirst CResult; /**< @brief result type */
	};

	/**
	 *	@brief compares the flag (specialization for the flag being false)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CChoose<false MSVC_OMMIT_ARG(GppDummy)> {
		typedef CSecond CResult; /**< @brief result type */
	};

public:
	typedef typename CChoose<b_choose_first MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief result type */
};

/**
 *	@brief removes duplicate items from a typelist
 *	@tparam CList is a typelist
 *	@note This leaves the last occurence of any duplicate item, removes the preceding ones.
 */
template <class CList>
class CUniqueTypelist {
protected:
	typedef typename CList::CHead CHead; /**< @brief list head */
	typedef typename CList::CTail CRest; /**< @brief the rest of the list */
	typedef typename CUniqueTypelist<CRest>::CResult CUniqueR; /**< @brief the rest of the list, without duplicate items */

	/**
	 *	@brief intermediates, stored as enum
	 */
	enum {
		b_duplicate_head = CFindTypelistItem<CRest, CHead>::b_found /**< @brief flag whether the head occurs in the rest of the list */
	};

public:
	typedef typename CChooseType<CUniqueR, CTypelist<CHead,
		CUniqueR>, b_duplicate_head>::CResult CResult; /**< @brief the filtered list */
};

/**
 *	@brief removes duplicate items from a typelist (specialization for an empty list, or the end of the list)
 */
template <>
class CUniqueTypelist<CTypelistEnd> {
public:
	typedef CTypelistEnd CResult; /**< @brief the filtered list */
};

namespace tl_msvc6 {

/**
 *	@brief sorting container (unidentified msvc bug workarround)
 */
struct CSortWithDefaultComparison {
	/**
	 *	@brief helper environment that peels head off of the list (need two first elements at a time)
	 *	@tparam CHead0 is head of the list
	 */
	template <class CHead0>
	struct CPeelHead {
		/**
		 *	@brief sorting pass
		 *
		 *	@tparam CList is list to be sorted (without CHead0)
		 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
		 */
		template <class CList MSVC_OMMIT_ARG(class GppDummy)>
		struct CSortPass {
			typedef typename CList::CHead CHead1; /**< @brief the second head element in the list */
			typedef typename CList::CTail CRest; /**< @brief the remaining elements of the list */

			/**
			 *	@brief intermediate, stored as enum
			 */
			enum {
				b_swap = CHead1::IS_OMMIT(template) CCompare<CHead0>::b_result /**< @brief swap flag */
				// test non-violation, otherwise will loop on lists with duplicate items
			};

			typedef typename CChooseType<CHead0, CHead1, !b_swap>::CResult COrderedFirst; /**< @brief the element that is ordered first */
			typedef typename CChooseType<CHead0, CHead1, b_swap>::CResult COrderedSecond; /**< @brief the element that is ordered second */
			typedef CTypelist<COrderedFirst, typename CPeelHead<COrderedSecond>::IS_OMMIT(template)
				CSortPass<CRest MSVC_OMMIT_ARG(GppDummy)>::CResult> CResult; /**< @brief result after a single sort pass */

			/**
			 *	@brief result, stored as enum
			 */
			enum {
				b_swapped = b_swap || CPeelHead<COrderedSecond>::IS_OMMIT(template)
					CSortPass<CRest MSVC_OMMIT_ARG(GppDummy)>::b_swapped /**< @brief list change flag (determines when the sorting is over) */
			};
		};

		/**
		 *	@brief sorting pass (specialization for the end of the list, or for an empty list)
		 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
		 */
		template <MSVC_OMMIT(class GppDummy)>
		struct CSortPass<CTypelistEnd MSVC_OMMIT_ARG(GppDummy)> {
			/**
			 *	@brief result, stored as enum
			 */
			enum {
				b_swapped = false /**< @brief list change flag (determines when the sorting is over) */
				// nothing to swap
			};

			typedef CTypelist<CHead0, CTypelistEnd> CResult; /**< @brief result after a single sort pass */
		};
	};

	/**
	 *	@brief sorting algorithm
	 *
	 *	@tparam CList is the list to be sorted
	 *	@tparam GppDummy0 is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class CList MSVC_OMMIT_ARG(class GppDummy0)>
	struct CSort {
		/**
		 *	@brief next pass environment (msvc partial specialization issue workarround)
		 *	@tparam CPartiallySorted is partially sorted list
		 */
		template <class CPartiallySorted>
		struct CNextPass {
			/**
			 *	@brief decides whether to execute the next sorting pass
			 *
			 *	@tparam b_do_iterate is iteration flag
			 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
			 */
			template <const bool b_do_iterate MSVC6_OMMIT_ARG(class GppDummy)>
			struct CIf {
				typedef CPartiallySorted CResult; /**< completely sorted result */
			};

			/**
			 *	@brief decides whether to execute the next sorting pass (specialization for continued sorting)
			 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
			 */
			template <MSVC6_OMMIT(class GppDummy)>
			struct CIf<true MSVC6_OMMIT_ARG(GppDummy)> {
				typedef typename CSort<CPartiallySorted MSVC_OMMIT_ARG(void)>::CResult CResult; /**< completely sorted result */
			};
		};

		typedef typename CPeelHead<typename CList::CHead>::IS_OMMIT(template)
			CSortPass<typename CList::CTail MSVC_OMMIT_ARG(void)> CSortPassImpl; /**< @brief sort pass implementation */
		typedef typename CSortPassImpl::CResult CPartiallySortedList; /**< partially sorted list */

		/**
		 *	@brief intermediate, stored as enum
		 */
		enum {
			b_need_next = CSortPassImpl::b_swapped /**< @brief continue sorting flag */
		};

		typedef typename CNextPass<CPartiallySortedList>::IS_OMMIT(template)
			CIf<b_need_next MSVC6_OMMIT_ARG(void)>::CResult CResult; /**< @brief completely sorted result */
	};

	/**
	 *	@brief sorting algorithm (specialization for an empty list)
	 *	@tparam GppDummy0 is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy0)>
	struct CSort<CTypelistEnd MSVC_OMMIT_ARG(GppDummy0)> {
		typedef CTypelistEnd CResult; /**< @brief completely sorted result */
	};
};

} // ~tl_msvc6

/**
 *	@brief sorts a typelist, based on "default" predicates implemented in the items (types)
 *	@tparam CList is list to be sorted
 *	@note See CCTSize::CCompare as an example of the comparison predicate.
 */
template <class CList>
struct CSortTypelist {
	typedef typename tl_msvc6::CSortWithDefaultComparison::CSort<CList
		MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief result (the sorted list) */
};

/**
 *	@brief sorts a typelist, using an explicit comparison template
 *
 *	The comparison wrapper is implemented as follows:
 *	@code
 *	struct CComparisonWrapper_Example {
 *		template <class A, class B>
 *		struct CCompare {
 *			enum {
 *				b_result = int(A::x) < int(B::x) // implement less-than comparison
 *			};
 *		};
 *	};
 *	@endcode
 *
 *	@tparam CList is list to be sorted
 *	@tparam CComparisonWrapper is a wrapper, containing the comparison template
 */
template <class CList, class CComparisonWrapper>
class CSortTypelist2 {
protected:
	/**
	 *	@brief helper environment that peels head off of the list (need two first elements at a time)
	 *	@tparam CHead0 is head of the list
	 */
	template <class CHead0>
	struct CPeelHead {
		/**
		 *	@brief sorting pass
		 *
		 *	@tparam CList is list to be sorted (without CHead0)
		 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
		 */
		template <class CList0 MSVC_OMMIT_ARG(class GppDummy)>
		struct CSortPass {
			typedef typename CList0::CHead CHead1; /**< @brief the second head element in the list */
			typedef typename CList0::CTail CRest; /**< @brief the remaining elements of the list */

			/**
			 *	@brief intermediate, stored as enum
			 */
			enum {
				b_swap = CComparisonWrapper::IS_OMMIT(template) CCompare<CHead1, CHead0>::b_result /**< @brief swap flag */
				// test non-violation, otherwise will loop on lists with duplicate items
			};

			typedef typename CChooseType<CHead0, CHead1, !b_swap>::CResult COrderedFirst; /**< @brief the element that is ordered first */
			typedef typename CChooseType<CHead0, CHead1, b_swap>::CResult COrderedSecond; /**< @brief the element that is ordered second */
			typedef CTypelist<COrderedFirst, typename CPeelHead<COrderedSecond>::IS_OMMIT(template)
				CSortPass<CRest MSVC_OMMIT_ARG(GppDummy)>::CResult> CResult; /**< @brief result after a single sort pass */

			/**
			 *	@brief result, stored as enum
			 */
			enum {
				b_swapped = b_swap || CPeelHead<COrderedSecond>::IS_OMMIT(template)
					CSortPass<CRest MSVC_OMMIT_ARG(GppDummy)>::b_swapped /**< @brief list change flag (determines when the sorting is over) */
			};
		};

		/**
		 *	@brief sorting pass (specialization for the end of the list, or for an empty list)
		 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
		 */
		template <MSVC_OMMIT(class GppDummy)>
		struct CSortPass<CTypelistEnd MSVC_OMMIT_ARG(GppDummy)> {
			/**
			 *	@brief result, stored as enum
			 */
			enum {
				b_swapped = false /**< @brief list change flag (determines when the sorting is over) */
				// nothing to swap
			};

			typedef CTypelist<CHead0, CTypelistEnd> CResult; /**< @brief result after a single sort pass */
		};
	};

	/**
	 *	@brief sorting algorithm
	 *
	 *	@tparam CList is the list to be sorted
	 *	@tparam GppDummy0 is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class CList0 MSVC_OMMIT_ARG(class GppDummy0)>
	struct CSort {
		/**
		 *	@brief next pass environment (msvc partial specialization issue workarround)
		 *	@tparam CPartiallySorted is partially sorted list
		 */
		template <class CPartiallySorted>
		struct CNextPass {
			/**
			 *	@brief decides whether to execute the next sorting pass
			 *
			 *	@tparam b_do_iterate is iteration flag
			 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
			 */
			template <const bool b_do_iterate MSVC6_OMMIT_ARG(class GppDummy)>
			struct CIf {
				typedef CPartiallySorted CResult; /**< completely sorted result */
			};

			/**
			 *	@brief decides whether to execute the next sorting pass (specialization for continued sorting)
			 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
			 */
			template <MSVC6_OMMIT(class GppDummy)>
			struct CIf<true MSVC6_OMMIT_ARG(GppDummy)> {
				typedef typename CSort<CPartiallySorted MSVC_OMMIT_ARG(GppDummy0)>::CResult CResult; /**< completely sorted result */
			};
		};

		typedef typename CPeelHead<typename CList0::CHead>::IS_OMMIT(template)
			CSortPass<typename CList0::CTail MSVC_OMMIT_ARG(void)> CSortPassImpl; /**< @brief sort pass implementation */
		typedef typename CSortPassImpl::CResult CPartiallySortedList; /**< partially sorted list */

		/**
		 *	@brief intermediate, stored as enum
		 */
		enum {
			b_need_next = CSortPassImpl::b_swapped /**< @brief continue sorting flag */
		};

		typedef typename CNextPass<CPartiallySortedList>::IS_OMMIT(template)
			CIf<b_need_next MSVC6_OMMIT_ARG(void)>::CResult CResult; /**< @brief completely sorted result */
	};

	/**
	 *	@brief sorting algorithm (specialization for an empty list)
	 *	@tparam GppDummy0 is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CSort<CTypelistEnd MSVC_OMMIT_ARG(GppDummy)> {
		typedef CTypelistEnd CResult; /**< @brief completely sorted result */
	};

	// msvc6 has problems to compile this, unless it is right here (can't be in an external template)

public:
	typedef typename CSort<CList MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief completely sorted result */
};

/**
 *	@brief concatenates two typelists
 *
 *	@tparam CFirstList is the first typelist, or CTypelistEnd for an empty list
 *	@tparam CSecondList is the second typelist, or CTypelistEnd for an empty list
 */
template <class CFirstList, class CSecondList>
class CConcatTypelist {
protected:
	/**
	 *	@brief concatenation helper (msvc partial specialization issue workarround)
	 *
	 *	@tparam CBegin is the beginning of the first list being recursed through
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class CBegin MSVC_OMMIT_ARG(class GppDummy)>
	struct CConcat {
		typedef typename CConcat<typename CBegin::CTail MSVC_OMMIT_ARG(GppDummy)>::CResult CTail; /**< @brief concatenated tail */
		typedef CTypelist<typename CBegin::CHead, CTail> CResult; /**< @brief result list */
	};

	/**
	 *	@brief concatenation helper (msvc partial specialization
	 *		issue workarround; specialization for an empty list)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CConcat<CTypelistEnd MSVC_OMMIT_ARG(GppDummy)> {
		typedef CSecondList CResult; /**< @brief result list */
	};

public:
	typedef typename CConcat<CFirstList MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief the concatenated list */
};

namespace tl_msvc6 {

/**
 *	@brief no-op unary transformation wrapper (workarround for msvc
 *		which requires model of the functor for syntax analysis)
 */
class CNoOpConstructorWrapper {
private:
	/**
	 *	@brief no-op unary transformation template
	 *	@tparam n_value is the argument value
	 *	@note This is inaccessible btw, will cause error if instantiated.
	 */
	template <const int n_value>
	struct CConstruct {
		typedef void CResult; /**< @brief result */
	};
};

/**
 *	@brief no-op unary transformation wrapper (workarround for msvc
 *		which requires model of the functor for syntax analysis)
 */
class CNoOpTransformWrapper {
private:
	/**
	 *	@brief no-op unary transformation template
	 *	@tparam COther is the argument type
	 *	@note This is inaccessible btw, will cause error if instantiated.
	 */
	template <class COther>
	struct CTransform {
		typedef COther CResult; /**< @brief result */
	};
};

/**
 *	@brief no-op binary transformation wrapper (workarround for msvc
 *		which requires model of the functor for syntax analysis)
 */
class CNoOpTransformWrapper2 {
private:
	/**
	 *	@brief no-op binary transformation template
	 *
	 *	@tparam CLeft is the argument type
	 *	@tparam CRight is the argument type
	 *
	 *	@note This is inaccessible btw, will cause error if instantiated.
	 */
	template <class CLeft, class CRight>
	struct CTransform {
		typedef CLeft CResult; /**< @brief result */
	};
};

/**
 *	@brief no-op functional wrapper (workarround for msvc
 *		which requires model of the functor for syntax analysis)
 */
struct CNoOpRunWrapper {
protected:
	/**
	 *	@brief dummy loop template
	 *	@tparam CType is type specialization for the loop
	 */
	template <class CType>
	struct CLoop {
		/**
		 *	@brief function with the body of the loop
		 *	@tparam CContext is context type
		 *	@param[in] t_ctx is context of the loop call
		 */
		template <class CContext>
		static inline void Run(CContext UNUSED(t_ctx))
		{}
	};
};

/**
 *	@brief this is used to defer template instantiation
 *	@tparam CTypeWithResult is type of the function template with member type CResult
 */
template <class CTypeWithResult>
struct CDeferResultEval { // defers compilation, makes compiler happy, all is good.
	typedef typename CTypeWithResult::CResult CResult; /**< @brief result type */
};

/**
 *	@brief type construction invokation environment (workarround for msvc
 *		which requires model of the functor for syntax analysis)
 *	@tparam CConstructorWrapper is class, containing a template functor
 */
template <class CConstructorWrapper>
struct CConstructorEnv {
	struct CPrototypeCtr : public CNoOpConstructorWrapper {}; /**< @brief provide the default transformation for semantic check when compiling this template */
	struct CConstructWithDefault : public CConstructorWrapper, CPrototypeCtr {}; /**< @brief supply specialization-time functionality (order matters!) */
	// note that this does not work in G++, CPerformOpWithDefault::CTransform is ambiguous

	/**
	 *	@brief type construction invokation template
	 *	@tparam n_value is the argument value
	 */
	template <const int n_value>
	struct CConstruct {
		typedef typename CDeferResultEval<typename
			CConstructWithDefault::IS_OMMIT(template) CConstruct<n_value> >::CResult CResult; /**< @brief result type */
	};
};

/**
 *	@brief unary transform invokation environment (workarround for msvc
 *		which requires model of the functor for syntax analysis)
 *	@tparam COperationWrapper is class, containing a template functor
 */
template <class COperationWrapper>
struct CTransformEnv {
	struct CPrototypeOp : public CNoOpTransformWrapper {}; /**< @brief provide the default transformation for semantic check when compiling this template */
	struct CPerformOpWithDefault : public COperationWrapper, CPrototypeOp {}; /**< @brief supply specialization-time functionality (order matters!) */
	// note that this does not work in G++, CPerformOpWithDefault::CTransform is ambiguous

	/**
	 *	@brief unary transform invokation template
	 *	@tparam COther is the argument type
	 */
	template <class COther>
	struct CTransform {
		typedef typename CDeferResultEval<typename
			CPerformOpWithDefault::IS_OMMIT(template) CTransform<COther> >::CResult CResult; /**< @brief result type */
	};
};

/**
 *	@brief binary transform invokation environment (workarround for msvc
 *		which requires model of the functor for syntax analysis)
 *	@tparam COperationWrapper is class, containing a template functor
 */
template <class COperationWrapper>
struct CTransformEnv2 {
	struct CPrototypeOp : public CNoOpTransformWrapper2 {}; /**< @brief provide the default transformation for semantic check when compiling this template */
	struct CPerformOpWithDefault : public COperationWrapper, CPrototypeOp {}; /**< @brief supply specialization-time functionality (order matters!) */
	// note that this does not work in G++, CPerformOpWithDefault::CTransform is ambiguous

	/**
	 *	@brief binary transform invokation template
	 *
	 *	@tparam CLeft is the argument type
	 *	@tparam CRight is the argument type
	 */
	template <class CLeft, class CRight>
	struct CTransform {
		typedef typename CDeferResultEval<typename
			CPerformOpWithDefault::IS_OMMIT(template) CTransform<CLeft, CRight> >::CResult CResult; /**< @brief result type */
	};
};

/**
 *	@brief loop invokation environment (workarround for msvc
 *		which requires model of the functor for syntax analysis)
 *
 *	@tparam COperationWrapper is class, containing a template functor
 *	@tparam CType is type for which the loop is to be specialized
 *	@tparam CContext is type of the loop (runtime) context
 */
template <class COperationWrapper, class CType, class CContext>
struct CRunEnv {
	struct CPrototypeOp : public CNoOpRunWrapper {}; /**< @brief provide the default transformation for semantic check when compiling this template */
	struct CPerformOpWithDefault : public COperationWrapper, CPrototypeOp {}; /**< @brief supply specialization-time functionality (order matters!) */
	// note that this does not work in G++, CPerformOpWithDefault::CTransform is ambiguous

	/**
	 *	@brief function calling the body of the loop
	 *	@param[in] t_ctx is context of the loop call
	 */
	//template <class CContext> // sometimes doesn't infer the context correctly
	static inline void Run(CContext t_ctx)
	{
		CPerformOpWithDefault::IS_OMMIT(template) CLoop<CType>::Run(t_ctx);
	}
};

} // ~tl_msvc6

/**
 *	@brief transforms typelist entries by an unary template functor
 *
 *	@tparam CList is typelist type
 *	@tparam COperationWrapper is wrapper class, containing a template
 *		that performs typelist entries transformation
 */
template <class CList, class COperationWrapper>
class CTransformTypelist {
protected:
	/**
	 *	@brief transformation helper (msvc partial specialization issue workarround)
	 *
	 *	@tparam CListBegin is the list to be transformed
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class CListBegin MSVC_OMMIT_ARG(class GppDummy)>
	struct CRunTransform {
		typedef typename CRunTransform<typename CListBegin::CTail MSVC_OMMIT_ARG(GppDummy)>::CResult CTransformedTail; /**< @brief transformed tail of the typelist */
		typedef typename CListBegin::CHead CHead; /**< @brief the original head of the list */
#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER <= 1200
		typedef typename tl_msvc6::CTransformEnv<COperationWrapper>::IS_OMMIT(template) CTransform<CHead>::CResult CNewHead;
#else // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200
		typedef typename COperationWrapper::IS_OMMIT(template) CTransform<CHead>::CResult CNewHead; /**< @brief transformed head of the list */
#endif // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200

		typedef CTypelist<CNewHead, CTransformedTail> CResult; /**< @brief the transformed list */
	};

	/**
	 *	@brief transformation helper (msvc partial specialization
	 *		issue workarround; specialization for the end of the list, or an empty list)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CRunTransform<CTypelistEnd MSVC_OMMIT_ARG(GppDummy)> {
		typedef CTypelistEnd CResult; /**< @brief the transformed list */
	};

public:
	typedef typename CRunTransform<CList MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief the transformed list */
};

/**
 *	@brief binary transform, making a CTypePair out of the two types
 */
struct CPairTransformWrapper {
	/**
	 *	@brief no-op binary transformation template
	 *
	 *	@tparam CLeft is the argument type
	 *	@tparam CRight is the argument type
	 *
	 *	@note This is inaccessible btw, will cause error if instantiated.
	 */
	template <class CLeft, class CRight>
	struct CTransform {
		typedef CTypePair<CLeft, CRight> CResult; /**< @brief result */
	};
};

/**
 *	@brief transforms typelist entries by a binary template functor
 *
 *	@tparam CLeftList is typelist type (on the left side of the binary function)
 *	@tparam CRightList is typelist type (on the right side of the binary function)
 *	@tparam COperationWrapper is wrapper class, containing a template
 *		that performs transformation of pairs of typelist entries (binary transform)
 */
template <class CLeftList, class CRightList, class COperationWrapper>
class CTransformTypelist2 {
protected:
	typedef typename CTypelistAssert<int(CTypelistLength<CLeftList>::n_result) ==
		int(CTypelistLength<CRightList>::n_result)>::TYPELISTS_MUST_BE_OF_THE_SAME_LENGTH CAssertListsLength; /**< @brief same list length assertion */
	// make sure both lists are of the same length

	/**
	 *	@brief transformation helper (msvc partial specialization issue workarround)
	 *
	 *	@tparam CLists is specialization of CTypePair, containing the lists to be transformed
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class CLists MSVC_OMMIT_ARG(class GppDummy)>
	struct CRunTransform {
		typedef typename CLists::CFirst CLeft; /**< @brief left typelist */
		typedef typename CLists::CSecond CRight; /**< @brief right typelist */
		// get left, right list

		typedef CTypePair<typename CLeft::CTail, typename CRight::CTail> CRestOfLists; /**< @brief tails of lists in CTypePair */
		typedef typename CRunTransform<CRestOfLists MSVC_OMMIT_ARG(GppDummy)>::CResult CTransformedTail; /**< @brief transformed tails of the lists */

		typedef typename CLeft::CHead CLHead; /**< @brief head of the left typelist */
		typedef typename CRight::CHead CRHead; /**< @brief head of the right typelist */
#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER <= 1200
		typedef typename tl_msvc6::CTransformEnv2<COperationWrapper>::IS_OMMIT(template) CTransform<CLHead, CRHead>::CResult CNewHead;
#else // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200
		typedef typename COperationWrapper::IS_OMMIT(template) CTransform<CLHead, CRHead>::CResult CNewHead; /**< @brief transformed head */
#endif // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200

		typedef CTypelist<CNewHead, CTransformedTail> CResult; /**< @brief the transformed list */
	};

	/**
	 *	@brief transformation helper (msvc partial specialization
	 *		issue workarround; specialization for the end of the list, or an empty list)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CRunTransform<CTypePair<CTypelistEnd, CTypelistEnd> MSVC_OMMIT_ARG(GppDummy)> {
		typedef CTypelistEnd CResult; /**< @brief the transformed list */
	};

public:
	typedef typename CRunTransform<CTypePair<CLeftList, CRightList> MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief the concatenated list */
};

namespace tl_msvc6 {

/**
 *	@brief for-each environment (workarround for the msvc partial specialization issue)
 *
 *	@tparam CFunctor is wrapper, containing the functor template
 *	@tparam CContext is runtime context type
 */
template <class CFunctor, class CContext>
struct CForEachEnv {
	/**
	 *	@brief iteration helper (msvc partial specialization issue workarround)
	 *
	 *	@tparam CList is typelist to iterate over
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class CList MSVC_OMMIT_ARG(class GppDummy)>
	struct CRun {
		typedef typename CList::CHead CHead; /**< @brief head of the list */

		/**
		 *	@brief invokes the functor for the current head and with runtime context
		 *	@param[in] t_ctx is runtime context for the functor
		 */
		static inline void Run(CContext t_ctx)
		{
			//CFunctor::IS_OMMIT(template) Run<CHead>(t_ctx); // compiles, but does not instantiate
#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER <= 1200
			tl_msvc6::CRunEnv<CFunctor, CHead, CContext>::Run(t_ctx);
#else // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200
			CFunctor::IS_OMMIT(template) CLoop<CHead>::Run(t_ctx);
#endif // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200
			CRun<MSVC_OMMIT(typename) CList::CTail MSVC_OMMIT_ARG(GppDummy)>::Run(t_ctx);
		}
	};

	/**
	 *	@brief iteration helper (msvc partial specialization
	 *		issue workarround; specialization for the end of the list, or an empty list)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CRun<CTypelistEnd MSVC_OMMIT_ARG(GppDummy)> {
		static inline void Run(CContext UNUSED(t_ctx))
		{}
	};
};

} // ~tl_msvc6

/**
 *	@brief for-each style iteration over typelist items, at runtime
 *
 *	Use with a functor wrapper like this:
 *	@code
 *	struct CFunctor_Example {
 *		// CTypelistItem is item of the typelist (this is specialized
 *		// for all the items and called sequentially)
 *		template <class CTypelistItem>
 *		struct CLoop {
 *			// context is runtime context, passed to the
 *			// functor (the same value for all the elements)
 *			// the type of the context can be anything, and is
 *			// specified as the CContext parameter of this template
 *			void Run(int context)
 *			{
 *			}
 *		};
 *	};
 *	@endcode
 *
 *	This is particularly useful with references as those would be implicitly
 *	dropped from the function template specialization in CTypelistForEach:
 *	@code
 *	struct CSum {
 *		template <class A>
 *		struct CLoop {
 *			static void Run(int &r_n_context)
 *			{
 *				r_n_context += A::n_size;
 *			}
 *		};
 *	};
 *
 *	int n_sum = 0;
 *	CTypelistForEach_Context<sequence, CSum, int&>::Run(n_sum);
 *	@endcode
 *
 *	@tparam CList is typelist to iterate over
 *	@tparam CFunctor is wrapper, containing the functor template
 *	@tparam CContext is context type
 *
 *	@note In case CContext is not a reference to a type, it is possible
 *		to use CTypelistForEach where the context type is inferred automatically
 *		(which does not work correctly for references in msvc6).
 */
template <class CList, class CFunctor, class CContext>
struct CTypelistForEach_Context { // for cases when context is not correctly inferred from the function call
	/**
	 *	@brief loop invokation function
	 *	@param[in] t_ctx is runtime value of the loop context
	 */
	static inline void Run(CContext t_ctx)
	{
		tl_msvc6::CForEachEnv<CFunctor, CContext>::IS_OMMIT(template) CRun<CList MSVC_OMMIT_ARG(void)>::Run(t_ctx);
	}
};

/**
 *	@brief for-each style iteration over typelist items, at runtime
 *
 *	Use with a functor wrapper like this:
 *	@code,
 *	struct CFunctor_Example {
 *		// CTypelistItem is item of the typelist (this is specialized
 *		// for all the items and called sequentially)
 *		template <class CTypelistItem>
 *		struct CLoop {
 *			// context is runtime context, passed to the
 *			// functor (the same value for all the elements)
 *			// the type of the context can be anything
 *			void Run(int context)
 *			{
 *			}
 *		};
 *	};
 *	@endcode
 *
 *	@tparam CList is typelist to iterate over
 *	@tparam CFunctor is wrapper, containing the functor template
 *
 *	@note See also CTypelistForEach_Context.
 */
template <class CList, class CFunctor>
struct CTypelistForEach {
	/**
	 *	@brief loop invokation function
	 *	@tparam CContext is context data type (such as structure with loop arguments)
	 *	@param[in] t_ctx is runtime value of the loop context
	 *	@note In case CContext is a reference to a type, use CTypelistForEach_Context instead.
	 */
	template <class CContext>
	static inline void Run(CContext t_ctx)
	{
		CTypelistForEach_Context<CList, CFunctor, CContext>::Run(t_ctx); // just reuse
	}
};

/**
 *	@brief filters a typelist
 *
 *	Keeps all typelist items <tt>Ty</tt> for which <tt>CPredicateWrapper::CPredicate<Ty>::b_result != false</tt> .
 *
 *	@tparam CList is typelist type
 *	@tparam CPredicate is a predicate, deciding whether to keep the types
 *
 *	@note See also CFilterTypelist2.
 */
template <class CList, class CPredicateWrapper>
class CFilterTypelist {
protected:
	/**
	 *	@brief filter helper (msvc partial specialization issue workarround)
	 *
	 *	@tparam CListBegin is typelist being filtered
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class CListBegin MSVC_OMMIT_ARG(class GppDummy)>
	struct CFilter {
		typedef typename CListBegin::CHead CHead; /**< @brief head of the list */

		/**
		 *	@brief intermediate, stored as enum
		 */
		enum {
			b_keep_head = CPredicateWrapper::IS_OMMIT(template) CPredicate<CHead>::b_result /**< @brief predicate value for the current item */
		};

		typedef typename CFilter<typename CListBegin::CTail MSVC_OMMIT_ARG(GppDummy)>::CResult CFilteredTail; /**< @brief filtered tail of the list */
		typedef typename CChooseType<CTypelist<CHead, CFilteredTail>, CFilteredTail, b_keep_head>::CResult CResult; /**< @brief filtered list */
	};

	/**
	 *	@brief filter helper (msvc partial specialization issue workarround;
	 *		specialization for the end of the list, or an empty list)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CFilter<CTypelistEnd MSVC_OMMIT_ARG(GppDummy)> {
		typedef CTypelistEnd CResult; /**< @brief filtered list */
	};

public:
	typedef typename CFilter<CList MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief filtered list */
};

/**
 *	@brief filters a typelist with additional context
 *
 *	Keeps all typelist items <tt>Ty</tt> for which
 *	<tt>CPredicateWrapper::CPredicate<Ty, CPredicateContext>::b_result != false</tt> .
 *
 *	@tparam CList is typelist type
 *	@tparam CPredicate is a predicate, deciding whether to keep the types
 *	@tparam CPredicateContext is predicate context (e.g. a reference item, etc.)
 *
 *	@note See also CFilterTypelist.
 */
template <class CList, class CPredicateWrapper, class CPredicateContext>
class CFilterTypelist2 {
protected:
	/**
	 *	@brief filter helper (msvc partial specialization issue workarround)
	 *
	 *	@tparam CListBegin is typelist being filtered
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <class CListBegin MSVC_OMMIT_ARG(class GppDummy)>
	struct CFilter {
		typedef typename CListBegin::CHead CHead; /**< @brief head of the list */

		enum {
			b_keep_head = (CPredicateWrapper::IS_OMMIT(template) CPredicate<CHead, CPredicateContext>::b_result) /**< @brief predicate value for the current item */
			// note that the parentheses are required
		};

		typedef typename CFilter<typename CListBegin::CTail MSVC_OMMIT_ARG(GppDummy)>::CResult CFilteredTail; /**< @brief filtered tail of the list */
		typedef typename CChooseType<CTypelist<CHead, CFilteredTail>, CFilteredTail, b_keep_head>::CResult CResult; /**< @brief filtered list */
	};

	/**
	 *	@brief filter helper (msvc partial specialization issue workarround;
	 *		specialization for the end of the list, or an empty list)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CFilter<CTypelistEnd MSVC_OMMIT_ARG(GppDummy)> {
		typedef CTypelistEnd CResult; /**< @brief filtered list */
	};

public:
	typedef typename CFilter<CList MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief filtered list */
};

/**
 *	@brief runtime comparison predicate wrapper
 *	@tparam TScalar is scalar type for comparison (default is <tt>int</tt>)
 */
template <class TScalar = int>
struct CRuntimeCompare_CCTSize {
	/**
	 *	@brief runtime comparison predicate
	 *	@tparam CPivot is type of compile-type constant to compare against
	 */
	template <class CPivot>
	struct CPredicate {
		/**
		 *	@brief implementation of the equality comparison operator
		 *	@param[in] n_value is runtime value to compare
		 *	@return Returns true if the value of <tt>CPivot</tt> equals the given value.
		 */
		static inline bool b_Equal(TScalar n_value)
		{
			return TScalar(CPivot::n_size) == n_value;
		}

		/**
		 *	@brief implementation of the less-than comparison operator
		 *	@param[in] n_value is runtime value to compare
		 *	@return Returns true if the value of <tt>CPivot</tt> is less than the given value.
		 */
		static inline bool b_LessThan(TScalar n_value)
		{
			return TScalar(CPivot::n_size) < n_value;
		}
	};
};

/**
 *	@brief runtime binary decision tree template with explicit runtime context type
 *
 *	The input list must be sorted and without duplicate values. The duplicate
 *	values only affect performance, sorting is essential for correctness.
 *	Neither one is checked because of the lack of comparison operators: requiring
 *	the caller to also provide comparison would reduce ease of use.
 *
 *	@tparam CSortedUniqueList is sorted typelist with duplicate values removed
 *	@tparam CFunctor is functor template wrapper (see CTypelistForEach for description)
 *	@tparam CContext is runtime context data type
 *	@tparam CValueType is data type of runtime value
 *	@tparam CRuntimeCompare is runtime compare predicate (see CRuntimeCompare_CCTSize)
 *
 *	@note In case CContext is not a reference to a type,
 *		it is possible to use the less-verbose CMakeDecisionTree.
 */
template <class CSortedUniqueList, class CFunctor,
	class CContext, class CValueType = int,
	class CRuntimeCompare = CRuntimeCompare_CCTSize<int> >
class CMakeDecisionTree_Context { // todo - make a decision tree where the context is also a param
protected:
	typedef CSortedUniqueList CList; /**< @brief list type */

	/**
	 *	@brief list length stored as enum
	 */
	enum {
		n_list_length = CTypelistLength<CList>::n_result /**< @brief length of the list */
	};

	typedef typename CTypelistAssert<(n_list_length > 0)>::TYPELIST_MUST_BE_NON_EMPTY CLengthAssert; /**< @brief nonzero length assertion */

public: // must be public, otherwise CDecide cannot access CDecisionEnv when recursing
	/**
	 *	@brief decision tree node environment (msvc partial specialization issue workarround)
	 *	@tparam n_first is zero-based index of the first element in the current range
	 *	@note This does not do a true tree search, rather it implements interval halving.
	 */
	template <const int n_first>
	struct CDecisionEnv {
		/**
		 *	@brief decision tree node
		 *
		 *	@tparam n_length is number of elements in the current range
		 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
		 */
		template <const int n_length MSVC_OMMIT_ARG(class GppDummy)>
		struct CNode {
			/**
			 *	@brief decision indices stored as enums
			 */
			enum {
				n_half = (n_length + 1) / 2, /**< @brief half of the length (round up, comparison is less than) */
				n_split = n_first + n_half, /**< @brief position where the lists split to left and right */
				n_pivot = n_split - 1, /**< @brief zero-based index of the pivot element (must be in the <tt>[n_first, n_split)</tt> range) */
				n_rest = n_length - n_half /**< @brief the remaining half of the length for the right child */
			};

			typedef typename CTypelistItemAt<CList, n_pivot>::CResult CPivot; /**< @brief pivot type */

			/**
			 *	@brief looks up a value in the decision tree, assumes it is present
			 *
			 *	@param[in] n_value is value to look for
			 *	@param[in] t_ctx is runtime context for the functor
			 */
			static inline void Run(CValueType n_value, CContext t_ctx)
			{
				if(CRuntimeCompare::IS_OMMIT(template) CPredicate<CPivot>::b_LessThan(n_value)) {
					CDecisionEnv<n_split>::IS_OMMIT(template) CNode<n_rest
						MSVC_OMMIT_ARG(GppDummy)>::Run(n_value, t_ctx); // pivot < n_value
				} else {
					CDecisionEnv<n_first>::IS_OMMIT(template) CNode<n_half
						MSVC_OMMIT_ARG(GppDummy)>::Run(n_value, t_ctx); // pivot >= n_value (pivot is here)
				}
			}

			/**
			 *	@brief looks up a value in the decision tree
			 *
			 *	@param[in] n_value is value to look for
			 *	@param[in] t_ctx is runtime context for the functor
			 *
			 *	@return Returns true if the value was found, false otherwise.
			 */
			static inline bool TryRun(CValueType n_value, CContext t_ctx)
			{
				if(CRuntimeCompare::IS_OMMIT(template) CPredicate<CPivot>::b_LessThan(n_value)) {
					return CDecisionEnv<n_split>::IS_OMMIT(template) CNode<n_rest
						MSVC_OMMIT_ARG(GppDummy)>::TryRun(n_value, t_ctx); // pivot < n_value
				} else {
					return CDecisionEnv<n_first>::IS_OMMIT(template) CNode<n_half
						MSVC_OMMIT_ARG(GppDummy)>::TryRun(n_value, t_ctx); // pivot >= n_value (pivot is here)
				}
			}

			/**
			 *	@brief looks up a value in the decision tree
			 *	@param[in] n_value is value to look for
			 *	@return Returns zero-based index of the value, or -1 in case it is not present in the list.
			 */
			static inline int n_BinarySearch(CValueType n_value)
			{
				if(CRuntimeCompare::IS_OMMIT(template) CPredicate<CPivot>::b_LessThan(n_value)) {
					return CDecisionEnv<n_split>::IS_OMMIT(template) CNode<n_rest
						MSVC_OMMIT_ARG(GppDummy)>::n_BinarySearch(n_value); // pivot < n_value
				} else {
					return CDecisionEnv<n_first>::IS_OMMIT(template) CNode<n_half
						MSVC_OMMIT_ARG(GppDummy)>::n_BinarySearch(n_value); // pivot >= n_value (pivot is here)
				}
			}
		};

		/**
		 *	@brief decision tree node (specialization for leaf nodes)
		 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
		 */
		template <MSVC_OMMIT(class GppDummy)>
		struct CNode<1 MSVC_OMMIT_ARG(GppDummy)> {
			typedef typename CTypelistItemAt<CList, n_first>::CResult CLeafType; /**< @brief leaf element type */

			/**
			 *	@brief looks up a value in the decision tree, assumes it is present
			 *
			 *	@param[in] n_value is value to look for
			 *	@param[in] t_ctx is runtime context for the functor
			 */
			static inline void Run(CValueType UNUSED(n_value), CContext t_ctx)
			{
				_ASSERTE(CRuntimeCompare::IS_OMMIT(template) CPredicate<CLeafType>::b_Equal(n_value));
				// assume that the value in the tree does exist

#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER <= 1200
				tl_msvc6::CRunEnv<CFunctor, CLeafType, CContext>::Run(t_ctx);
#else // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200
				CFunctor::IS_OMMIT(template) CLoop<CLeafType>::Run(t_ctx);
#endif // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200
				// t_odo - run the functor
			}

			/**
			 *	@brief looks up a value in the decision tree
			 *
			 *	@param[in] n_value is value to look for
			 *	@param[in] t_ctx is runtime context for the functor
			 *
			 *	@return Returns true if the value was found, false otherwise.
			 */
			static inline bool TryRun(CValueType n_value, CContext t_ctx)
			{
				if(CRuntimeCompare::IS_OMMIT(template) CPredicate<CLeafType>::b_Equal(n_value)) { // see if we found it
#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER <= 1200
					tl_msvc6::CRunEnv<CFunctor, CLeafType, CContext>::Run(t_ctx);
#else // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200
					CFunctor::IS_OMMIT(template) CLoop<CLeafType>::Run(t_ctx);
#endif // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200
					return true;
				}
				return false;
			}

			/**
			 *	@brief looks up a value in the decision tree
			 *	@param[in] n_value is value to look for
			 *	@return Returns zero-based index of the value, or -1 in case it is not present in the list.
			 */
			static inline int n_BinarySearch(CValueType n_value)
			{
				if(CRuntimeCompare::IS_OMMIT(template) CPredicate<CLeafType>::b_Equal(n_value))
					return n_first;
				return -1;
			}
		};
	};

public:
	/**
	 *	@brief looks up a value in the decision tree, assumes it is present
	 *
	 *	@param[in] n_value is value to look for
	 *	@param[in] t_ctx is runtime context for the functor
	 */
	static inline void Run(CValueType n_value, CContext t_ctx) // n_value assumed to be present in the tree
	{
		CDecisionEnv<0>::IS_OMMIT(template) CNode<n_list_length
			MSVC_OMMIT_ARG(void)>::Run(n_value, t_ctx);
	}

	/**
	 *	@brief looks up a value in the decision tree
	 *
	 *	@param[in] n_value is value to look for
	 *	@param[in] t_ctx is runtime context for the functor
	 *
	 *	@return Returns true if the value was found, false otherwise.
	 */
	static inline bool TryRun(CValueType n_value, CContext t_ctx) // n_value does not need to be present in the tree
	{
		return CDecisionEnv<0>::IS_OMMIT(template) CNode<n_list_length
			MSVC_OMMIT_ARG(void)>::TryRun(n_value, t_ctx);
	}

	/**
	 *	@brief looks up a value in the decision tree
	 *	@param[in] n_value is value to look for
	 *	@return Returns zero-based index of the value, or -1 in case it is not present in the list.
	 */
	static inline int n_BinarySearch(CValueType n_value) // returns zero-based index of the first occurence of n_value in the list, or -1 if not present
	{
		return CDecisionEnv<0>::IS_OMMIT(template) CNode<n_list_length
			MSVC_OMMIT_ARG(void)>::n_BinarySearch(n_value); // todo - verify this is indeed searching for the first occurence (it should, though)
	}
};

/**
 *	@brief runtime binary decision tree template
 *
 *	The input list must be sorted and without duplicate values. The duplicate
 *	values only affect performance, sorting is essential for correctness.
 *	Neither one is checked because of the lack of comparison operators: requiring
 *	the caller to also provide comparison would reduce ease of use.
 *
 *	@tparam CSortedUniqueList is sorted typelist with duplicate values removed
 *	@tparam CFunctor is functor template wrapper (see CTypelistForEach for description)
 *	@tparam CValueType is data type of runtime value
 *	@tparam CRuntimeCompare is runtime compare predicate (see CRuntimeCompare_CCTSize)
 *
 *	@note See also CMakeDecisionTree_Context.
 */
template <class CSortedUniqueList, class CFunctor, class CValueType = int,
	class CRuntimeCompare = CRuntimeCompare_CCTSize<int> >
struct CMakeDecisionTree {
	/**
	 *	@brief looks up a value in the decision tree, assumes it is present
	 *
	 *	@tparam CContext is runtime context data type
	 *
	 *	@param[in] n_value is value to look for
	 *	@param[in] t_ctx is runtime context for the functor
	 *
	 *	@note In case CContext is a reference to a type, use CMakeDecisionTree_Context::Run() instead.
	 */
	template <class CContext>
	static inline void Run(CValueType n_value, CContext t_ctx) // n_value assumed to be present in the tree
	{
		CMakeDecisionTree_Context<CSortedUniqueList, CFunctor,
			CContext, CValueType, CRuntimeCompare>::Run(n_value, t_ctx);
	}

	/**
	 *	@brief looks up a value in the decision tree
	 *
	 *	@tparam CContext is runtime context data type
	 *
	 *	@param[in] n_value is value to look for
	 *	@param[in] t_ctx is runtime context for the functor
	 *
	 *	@return Returns true if the value was found, false otherwise.
	 *
	 *	@note In case CContext is a reference to a type, use CMakeDecisionTree_Context::TryRun() instead.
	 */
	template <class CContext>
	static inline bool TryRun(CValueType n_value, CContext t_ctx) // n_value does not need to be present in the tree
	{
		return CMakeDecisionTree_Context<CSortedUniqueList, CFunctor,
			CContext, CValueType, CRuntimeCompare>::TryRun(n_value, t_ctx);
	}

	/**
	 *	@brief looks up a value in the sorted list
	 *	@param[in] n_value is value to look for
	 *	@return Returns zero-based index of the value, or -1 in case it is not present in the list.
	 */
	static inline int n_BinarySearch(CValueType n_value) // returns zero-based index of the first occurence of n_value in the list, or -1 if not present
	{
		return CMakeDecisionTree_Context<CSortedUniqueList, CFunctor,
			int, CValueType, CRuntimeCompare>::n_BinarySearch(n_value);
	}
};

/**
 *	@brief runtime binary search template
 *
 *	The input list must be sorted and without duplicate values. The duplicate
 *	values only affect performance, sorting is essential for correctness.
 *	Neither one is checked because of the lack of comparison operators: requiring
 *	the caller to also provide comparison would reduce ease of use.
 *
 *	@tparam CSortedUniqueList is sorted typelist with duplicate values removed
 *	@tparam CValueType is data type of runtime value
 *	@tparam CRuntimeCompare is runtime compare predicate (see CRuntimeCompare_CCTSize)
 */
template <class CSortedUniqueList, class CValueType = int,
	class CRuntimeCompare = CRuntimeCompare_CCTSize<int> >
struct CBinarySearch {
	/**
	 *	@brief looks up a value in the sorted list
	 *	@param[in] n_value is value to look for
	 *	@return Returns zero-based index of the value, or -1 in case it is not present in the list.
	 */
	static inline int n_BinarySearch(CValueType n_value) // returns zero-based index of the first occurence of n_value in the list, or -1 if not present
	{
		return CMakeDecisionTree<CSortedUniqueList, void, CValueType, CRuntimeCompare>::n_BinarySearch(n_value);
		// this uses CMakeDecisionTree with a dummy functor, as none is required for searching
		// it reuses the nodes implementation and search, much of the code is saved (otherwise
		// it is of course inacceptable to implement it like this)
	}
};

/**
 *	@brief CCTSize constructor wrapper for CTypelistIOTA
 */
struct CCTSize_ConstructorWrapper {
	/**
	 *	@brief constructor template
	 *	@tparam n_size is value of the type being constructed
	 */
	template <const int n_size>
	struct CConstruct {
		typedef CCTSize<n_size> CResult; /**< @brief result type */
	};
};

/**
 *	@brief sequence construction template
 *
 *	This constructs a sequence with a given number of elements.
 *	Each element is constructed from an integer. The integer, associated
 *	with the first element can be adjusted (zero by default), the step
 *	by which the next ones increase is always 1.
 *
 *	@tparam n_element_num is number of elements of the sequence (must be zero or greater)
 *	@tparam n_first_element is value associated with the first element
 *	@tparam CTypeConstructorWrapper is construction wrapper (see e.g. CCTSize_ConstructorWrapper)
 */
template <const int n_element_num, const int n_first_element = 0,
	class CTypeConstructorWrapper = CCTSize_ConstructorWrapper>
struct CTypelistIOTA {
protected:
	typedef typename CTypelistAssert<(n_element_num >= 0)>::SIZE_OF_THE_SEQUENCE_MUST_BE_NONNEGATIVE CLengthAssert; /**< @brief compile time assertion for sequence length nonnegativeness */

protected: // this should not work
#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER <= 1200
	typedef tl_msvc6::CConstructorEnv<CTypeConstructorWrapper> CTypeConstructor; /**< @brief type constructor (workarround for msvc aggresive syntactic check) */
#else // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200
	typedef CTypeConstructorWrapper CTypeConstructor; /**< @brief type constructor */
#endif // _MSC_VER && !__MWERKS__ && _MSC_VER <= 1200

	/**
	 *	@brief sequence construction template
	 *
	 *	@tparam n_remaining_num is the number of additional elements to generate
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <const int n_remaining_num MSVC_OMMIT_ARG(class GppDummy)>
	struct CIOTA {
		typedef typename CTypeConstructor::IS_OMMIT(template) CConstruct<n_first_element>::CResult CHead; /**< @brief type of the first element of the list */
		typedef typename CTypelistIOTA<n_remaining_num - 1,
			n_first_element + 1, CTypeConstructorWrapper>::CResult CTail; /**< @brief the rest of the list */
		typedef CTypelist<CHead, CTail> CResult; /**< @brief the resulting list */
	};

	/**
	 *	@brief sequence construction template (specialization for zero-length sequences)
	 *	@tparam GppDummy is compatibility workarround for g++ (full independent specialization inside a template)
	 */
	template <MSVC_OMMIT(class GppDummy)>
	struct CIOTA<0 MSVC_OMMIT_ARG(GppDummy)> {
		typedef CTypelistEnd CResult; /**< @brief the resulting list */
	};

public:
	typedef typename CIOTA<n_element_num MSVC_OMMIT_ARG(void)>::CResult CResult; /**< @brief the resulting list */
};

// todo - typelist head, typelist tail, typelist range

/**
 *	@brief compile-time predicate utilities
 */
namespace ct_pred {

/**
 *	@brief logical not operation
 *	@tparam CPred is predicate wrapper class
 */
template <class CPred>
struct CNot {
	/**
	 *	@brief predicate template
	 *	@tparam X is input type
	 */
	template <class X>
	struct CPredicate {
		/**
		 *	@brief result, stored as enum
		 */
		enum {
			b_result = !CPred::IS_OMMIT(template) CPredicate<X>::b_result /**< @brief result; logical negation of the original predicate */
		};
	};
};

/**
 *	@brief logical and operation
 *
 *	@tparam CLeftPred is predicate wrapper class
 *	@tparam CRightPred is predicate wrapper class
 */
template <class CLeftPred, class CRightPred>
struct CAnd {
	/**
	 *	@brief predicate template
	 *	@tparam X is input type
	 */
	template <class X>
	struct CPredicate {
		/**
		 *	@brief result, stored as enum
		 */
		enum {
			b_result = CLeftPred::IS_OMMIT(template) CPredicate<X>::b_result &&
				CRightPred::IS_OMMIT(template) CPredicate<X>::b_result /**< @brief result; logical and of the original predicates */
		};
	};
};

/**
 *	@brief logical or operation
 *
 *	@tparam CLeftPred is predicate wrapper class
 *	@tparam CRightPred is predicate wrapper class
 */
template <class CLeftPred, class CRightPred>
struct COr {
	/**
	 *	@brief predicate template
	 *	@tparam X is input type
	 */
	template <class X>
	struct CPredicate {
		/**
		 *	@brief result, stored as enum
		 */
		enum {
			b_result = CLeftPred::IS_OMMIT(template) CPredicate<X>::b_result ||
				CRightPred::IS_OMMIT(template) CPredicate<X>::b_result /**< @brief result; logical or of the original predicates */
		};
	};
};

/**
 *	@brief logical exclusive or operation
 *
 *	@tparam CLeftPred is predicate wrapper class
 *	@tparam CRightPred is predicate wrapper class
 */
template <class CLeftPred, class CRightPred>
struct CXor {
	/**
	 *	@brief predicate template
	 *	@tparam X is input type
	 */
	template <class X>
	struct CPredicate {
		/**
		 *	@brief result, stored as enum
		 */
		enum {
			b_result = !CLeftPred::IS_OMMIT(template) CPredicate<X>::b_result !=
				!CRightPred::IS_OMMIT(template) CPredicate<X>::b_result /**< @brief result; logical exclusive or of the original predicates */
		};
	};
};

} // ~ct_pred

/**
 *	@brief compile-time size utilities
 */
namespace cctsize_util {

/**
 *	@brief prints items of a typelist, composed of CCTSize specializations
 *	@tparam CList is list to be printed
 */
template <class CList>
struct CPrintSizeList {
	/**
	 *	@brief prints the list (space-separated values and a newline)
	 */
	static void Print()
	{
		printf("%d ", CList::CHead::n_size);
		CPrintSizeList<MSVC_OMMIT(typename) CList::CTail>::Print();
	}
};

/**
 *	@brief prints items of a typelist, composed of CCTSize specializations
 *		(specialization for an empty list or the end of the list)
 */
template <>
struct CPrintSizeList<CTypelistEnd> {
	/**
	 *	@brief prints the list (space-separated values and a newline)
	 */
	static void Print()
	{
		printf("\n");
	}
};

/**
 *	@brief even numver predicate wrapper
 */
struct CIsEven {
	/**
	 *	@brief predicate template
	 *	@tparam CSize is specialization of CCTSize
	 */
	template <class CSize>
	struct CPredicate {
		enum {
			b_result = (CSize::n_size & 1) != 0 /**< result; true if the input value is even, false if odd */
		};
	};
};

/**
 *	@brief odd numver predicate wrapper
 */
typedef ct_pred::CNot<CIsEven> CIsOdd;

/**
 *	@brief unary transformation wrapper (multiplies elements of a typelist by a constant)
 *	@tparam CFactor is factor (specialization of CCTSize)
 */
template <class CFactor>
struct CMultiplyBy {
	/**
	 *	@brief template argument, stored as enum
	 */
	enum {
		n_factor = CFactor::n_size /**< @brief value of factor */
	};

	/**
	 *	@brief unary transformation template
	 *	@tparam CSize is specialization of CCTSize
	 */
	template <class COther>
	struct CTransform {
		/**
		 *	@brief template argument, stored as enum
		 */
		enum {
			n_item = COther::n_size /**< @brief value of the current irem */
			// this helps, it breaks the compilation until instantiation
		};

		typedef CCTSize<n_item * n_factor> CResult; /**< @brief result type */
		// must still use enum
	};
};

/**
 *	@brief predicate wrapper for testing CCTSize numbers against a bit mask
 *	@tparam n_mask is a bit mask
 */
template <const int n_mask>
struct CMaskTest {
	/**
	 *	@brief predicate template
	 *	@tparam CSize is specialization of CCTSize
	 */
	template <class CSize>
	struct CPredicate {
		enum {
			b_result = ((n_mask >> CSize::n_size) & 1) == 1 /**< @brief see if the mask contains the given bit */
		};
	};
};

// todo - transform width from size2, height from size2, area from size2, circumference from size2

struct CPlus {
	template <class L, class R>
	struct CTransform {
		enum {
			l = L::n_size,
			r = R::n_size
		};
		typedef CCTSize<l + r> CResult;
	};
};

struct CMinus {
	template <class L, class R>
	struct CTransform {
		enum {
			l = L::n_size,
			r = R::n_size
		};
		typedef CCTSize<l - r> CResult;
	};
};

struct CMultiply {
	template <class L, class R>
	struct CTransform {
		enum {
			l = L::n_size,
			r = R::n_size
		};
		typedef CCTSize<l * r> CResult;
	};
};

struct CDivide {
	template <class L, class R>
	struct CTransform {
		enum {
			l = L::n_size,
			r = R::n_size
		};
		typedef CCTSize<l / r> CResult;
	};
};

struct CMax {
	template <class L, class R>
	struct CTransform {
		enum {
			l = L::n_size,
			r = R::n_size
		};
		typedef CCTSize<(l > r)? l : r> CResult;
	};
};

struct CMin {
	template <class L, class R>
	struct CTransform {
		enum {
			l = L::n_size,
			r = R::n_size
		};
		typedef CCTSize<(l > r)? r : l> CResult;
	};
};

} // ~cctsize_util

#if 0

/**
 *	@brief utility code; generates typelist constructors code
 *
 *	@param[in] n is maximal typelist length
 *	@param[in] n_max_line_length is maximum line length in characters (tabs are 4-wide)
 */
void Generate_TL_Constructors(const int n = 32, const size_t n_max_line_length = 80)
{
	// /**
	//  *	@def MakeTypelist3
	//  *	@brief makes a typelist
	//  *
	//  *	@param[in] a is a typelist item
	//  *	@param[in] b is a typelist item
	//  *	@param[in] c is a typelist item
	//  */
	// #define MakeTypelist3(a,b,c) CTypelist<a, MakeTypelist2(b, c) >

	const char *p_s_argnames = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	_ASSERTE(n > 0 && size_t(n) <= strlen(p_s_argnames));
	for(size_t i = 1, m = strlen(p_s_argnames); i < m; ++ i)
		_ASSERTE(p_s_argnames[i] > p_s_argnames[i - 1]); // unique, sorted
	// argument name list (single-chaøacter names)

	for(int i = 1; i <= n; ++ i) {
		printf(
			"\n"
			"/**\n"
			" *\t@def MakeTypelist%d\n"
			" *\t@brief makes a typelist with %d item%s\n"
			" *\n" + (i < 2), i, i, "s" + !(i > 1));
		for(int j = 0; j < i; ++ j)
			printf(" *\t@param[in] %c is a typelist item\n", p_s_argnames[j]);
		size_t n_col_num = 0;
		n_col_num += printf(" */\n"
			"#define MakeTypelist%d(", i);
		for(int j = 0; j < i; ++ j) {
			n_col_num += printf((j + 1 < i)? "%c," : "%c", p_s_argnames[j]);
			if(n_col_num >= n_max_line_length && j + 1 < i) { // not the last one
				printf(" \\\n\t");
				n_col_num = 4;
			}
		}
		if(!i)
			printf(") CTypelistEnd\n");
		if(i == 1)
			printf(") CTypelist<%c, CTypelistEnd>\n", p_s_argnames[0]);
		else {
			if(n_col_num < n_max_line_length - strlen("CTypelist<%c, MakeTypelist%d("))
				n_col_num += printf(") ");
			else {
				printf(") \\\n\t");
				n_col_num = 4;
			}
			n_col_num += printf("CTypelist<%c, MakeTypelist%d(", p_s_argnames[0], i - 1);
			for(int j = 0; j < i - 1; ++ j) {
				n_col_num += printf((j + 1 < i - 1)? "%c, " : "%c", p_s_argnames[j + 1]);
				if(n_col_num >= n_max_line_length && j + 1 < i - 1) { // not the last one
					printf("\\\n\t"); // the space is already there
					n_col_num = 4;
				}
			}
			printf(") >\n");
		}
	}
	printf("// mind the space at the end, that is significant in there!\n\n");
}

/**
 *	@brief utility code; generates safe typelist constructors code (not available in MSVC60)
 *
 *	@param[in] n is maximal typelist length
 *	@param[in] n_max_line_length is maximum line length in characters (tabs are 4-wide)
 */
void Generate_SafeTL_Constructors(const int n = 32, const size_t n_max_line_length = 80)
{
	// /**
	//  *\t@brief safe typelist constructor
	//  *\t@tparam TyFunction is a function pointer type (unrelated to typelist contents,
	//  *\t\tmerely a mechanism of resolving the types themselves using partial specialization)
	//  */
	// template <class TyFunction>
	// struct CSafeTypelistCtor;

	// /**
	//  *\t@brief safe typelist constructor
	//  *
	//  *\t@tparam x is the item of typelist
	//  */
	// template <class x>
	// struct CSafeTypelistCtor<void (*)(x)> {
	// \ttypedef MakeTypelist1(x) T; /**< @brief resulting typelist */
	// };

	const char *p_s_argnames = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	_ASSERTE(n > 0 && size_t(n) <= strlen(p_s_argnames));
	for(size_t i = 1, m = strlen(p_s_argnames); i < m; ++ i)
		_ASSERTE(p_s_argnames[i] > p_s_argnames[i - 1]); // unique, sorted
	// argument name list (single-chaøacter names)

	printf(
		"#if !defined(_MSC_VER) || defined(__MWERKS__) || _MSC_VER >= 1400\n\n"
		"/**\n"
		" *\t@brief safe typelist constructor\n"
		" *\t@tparam TyFunction is a function pointer type (unrelated to typelist contents,\n"
		" *\t\tmerely a mechanism of resolving the types themselves using partial specialization)\n"
		" *\t@note This is not available in MSVC60.\n"
		" */\n"
		"template <class TyFunction>\n"
		"struct CSafeTypelistCtor;\n");

	for(int i = 1; i <= n; ++ i) {
		printf((i > 1)?
			"\n"
			"/**\n"
			" *\t@brief makes a typelist with %d item%s\n"
			" *\n" :
			"\n"
			"/**\n"
			" *\t@brief makes a typelist with %d item%s\n", i, "s" + !(i > 1));
		for(int j = 0; j < i; ++ j)
			printf(" *\t@tparam %c is a typelist item\n", p_s_argnames[j]);
		printf(
			" *\n"
			" *\t@note This is not available in MSVC60.\n" + 3 * (i < 2));
		size_t n_col_num = 0;
		n_col_num += printf(" */\n"
			"template <");
		for(int j = 0; j < i; ++ j) {
			n_col_num += printf((j + 1 < i)? "class %c," : "class %c", p_s_argnames[j]);
			if(n_col_num >= n_max_line_length && j + 1 < i) { // not the last one
				printf("\n\t");
				n_col_num = 4;
			} else if(j + 1 < i)
				n_col_num += printf(" ");
		}
		printf(">\n");
		n_col_num = printf("struct CSafeTypelistCtor<void (*)(");
		for(int j = 0; j < i; ++ j) {
			n_col_num += printf((j + 1 < i)? "%c," : "%c", p_s_argnames[j]);
			if(n_col_num >= n_max_line_length && j + 1 < i) { // not the last one
				printf("\n\t");
				n_col_num = 4;
			} else if(j + 1 < i)
				n_col_num += printf(" ");
		}
		printf(")> {\n");
		n_col_num = printf("\ttypedef MakeTypelist%d(", i);
		const size_t n_shorter_len = n_max_line_length - strlen(") CResult; /**< @brief resulting typelist */");
		for(int j = 0; j < i; ++ j) {
			n_col_num += printf((j + 1 < i)? "%c," : "%c", p_s_argnames[j]);
			if(n_col_num >= ((j + 2 == i && n_col_num + 3 >= n_shorter_len)? n_shorter_len : n_max_line_length) && j + 1 < i) { // not the last one
				printf("\n\t\t");
				n_col_num = 8;
			} else if(j + 1 < i)
				n_col_num += printf(" ");
		}
		printf(") CResult; /**< @brief resulting typelist */\n};\n");
	}

	printf(
		"\n"
		"/**\n"
		" *\t@def MakeTypelist\n"
		" *\n"
		" *\t@brief makes a typelist (version with variable number of arguments)\n"
		" *\n"
		" *\t@param[in] ... is the list of items of typelist\n"
		" *\n"
		" *\t@return Returns declaration of a typelist containing all the entered types, in the given order.\n"
		" *\n"
		" *\t@note This only compiles on compilers, supporting variadic macros.\n"
		" *\t@note This is not available in MSVC60.\n"
		" */\n"
		"#define MakeTypelist(...) CSafeTypelistCtor<void (*)(__VA_ARGS__)>::CResult\n"
		"\n");

	printf(
		"/**\n"
		" *\t@def MakeTypelist_Safe\n"
		" *\n"
		" *\t@brief makes a typelist (version with variable number of arguments)\n"
		" *\n"
		" *\t@param[in] args is the list of items of typelist\n"
		" *\n"
		" *\t@return Returns declaration of a typelist containing all the entered types, in the given order.\n"
		" *\n"
		" *\t@note This is used with double parentheses, e.g. MakeTypelist_Safe((char, short, int)).\n"
		" *\t@note This is not available in MSVC60.\n"
		" */\n"
		"#define MakeTypelist_Safe(args) CSafeTypelistCtor<void (*)args>::CResult\n"
		"\n");

	printf("#endif // !_MSC_VER || __MWERKS__ || _MSC_VER >= 1400\n");
}

#endif // 0

#if 0 // debugging intellisense

struct CComparisonWrapper_Example {
	template <class A, class B>
	struct CCompare {
		enum {
			b_result = int(A::n_size) < int(B::n_size) // implement less-than comparison
		};
	};
};

struct CTransformWrapper_Example {
	template <class A>
	struct CTransform {
		typedef CCTSize<A::n_size + 1> CResult;
	};
};

struct CTransform2Wrapper_Example {
	template <class A, class B>
	struct CTransform {
		typedef CCTSize<A::n_size + B::n_size> CResult;
	};
};

struct CSum {
	template <class A>
	struct CLoop {
		static void Run(int &r_n_context)
		{
			r_n_context += A::n_size;
		}
	};
};

struct CPrint {
	template <class A>
	struct CLoop {
		static void Run(FILE *p_fw)
		{
			fprintf(p_fw, "%d ", A::n_size);
		}
	};
};

struct CIsEven {
	template <class A>
	struct CPredicate {
		enum {
			b_result = !(A::n_size & 1)
		};
	};
};

struct CIsEqual {
	template <class A, class B>
	struct CPredicate {
		enum {
			b_result = CIsSameType<A, B>::b_result
		};
	};
};

void TL_Demo()
{
	typedef CTypelist<int, CTypelistEnd> tl;
	tl::CHead h;
	Vector2<int> w;
	w.f_Length();
	CTypePair<Vector2f, float>::CFirst f;
	typedef MakeTypelist10(int, int, int, Vector2f, Vector4f, int, int, int, int, int) TL10;
	TL10::CTail::CTail::CTail::CHead ttth;
	TL10::CTail::CTail::CTail::CTail::CHead tttth;
	tttth.w = 7.0;
	ttth.x = 6.14f;
	typedef MakeTypelist_Safe((int, Vector2<int>, Vector3<int>, Vector4<int>)) vecs_safe;
	typedef MakeTypelist(int, Vector2i, Vector3i, Vector4i) vecs;
	Vector2<double> d2;
	d2.y = 7;
	vecs_safe::CTail::CHead v2;
	v2.f_Dot(v2);
	vecs::CTail::CTail::CHead v3;
	v2 = v3.v_zz();

	typedef CCTSize<3> s1;
	typedef CCTSize<4> s2;
	bool b = s1::CCompare<s2>::b_result;
	int ten = CTypelistLength<TL10>::n_result;
	bool b1 = CIsSameType<int, int>::b_result;
	typedef CTypelistItemAt<TL10, 4>::CResult R; // does not resolve, does not break
	typedef CTypelistAssert<true>::INDEX_OUT_OF_BOUNDS oob;
	R r; // does not resolve but does not break
	r.x = 7;
	r.zw(r.v_xy());
	Vector2f vv;
	vv.f_Dot(vv);
	int four = CFindTypelistItem<TL10, Vector4f>::n_index;
	bool yes = CFindTypelistItem<TL10, Vector4f>::b_found;
	bool no = CFindTypelistItem<TL10, Vector3f>::b_found;
	CChooseType<int, float, true>::CResult number;
	CChooseType<int, float, false>::CResult bnumber;
	Vector4d dd;
	number = dd.x;
	typedef CUniqueTypelist<TL10>::CResult lessThan10;
	CTypelistItemAt<lessThan10, 0>::CResult uh; // type information not available
	typedef MakeTypelist_Safe((CCTSize<5>, CCTSize<3>, CCTSize<0>, CCTSize<1>, CCTSize<4>, CCTSize<2>)) seq;
	typedef CSortTypelist<seq>::CResult sorted;
	typedef CTypelistItemAt<sorted, 0>::CResult smallest; // no type information available
	int nn = smallest::n_size;
	typedef CSortTypelist2<seq, CComparisonWrapper_Example>::CResult rev_sorted;
	typedef CConcatTypelist<seq, seq>::CResult double_seq;
	typedef CTransformTypelist<seq, CTransformWrapper_Example>::CResult transformed;
	typedef CTransformTypelist2<seq, seq, CTransform2Wrapper_Example>::CResult transformed2;
	int n_sum = 0;
	CTypelistForEach_Context<seq, CSum, int&>::Run(n_sum);
	CTypelistForEach<seq, CPrint>::Run(stdout); printf("\n");
	typedef CFilterTypelist<seq, CIsEven>::CResult even_seq;
	typedef CFilterTypelist2<seq, CIsEqual, CCTSize<5> >::CResult fives;
	CMakeDecisionTree_Context<sorted, CSum, int&>::Run(3, n_sum); // adds 3 to the sum (must be present)
	bool b_hadseven = CMakeDecisionTree<sorted, CPrint>::TryRun(7, stdout); // prints 7, if found
	int fourpos = CBinarySearch<sorted>::n_BinarySearch(4);
	typedef CTypelistIOTA<5>::CResult zero_to_five; // even resolves
	Vector2f v;
	v.x ++;
}

#endif // 0

#endif // !__TYPELIST_LIBRARY_INCLUDED
