// // in this source code I will demonstrate via example the "canonical" and compliant way of // simulating class template partial specialization and function templates partial ordering // both are not implemented in VC7 and from the simulation you will see that they are closely related // in the example I will simulate the Append class template which have 4 specializations // Part of the sample was also tested with Comeau C/C++ 4.3.0 online // although the code is perfectly compliant many compilers (like bcc 5.6 and gcc 3.03 which support partial stuff) can't // handle it (maybe some workaround can help). // #include #include #include #include #include using namespace ::Loki; // // Simulating function templates partial ordering (14.5.5.2): // The following simple example demonstrate the whole idea // template void f(T); // template void f(T*); // the functions are partial ordered and T* is more specialized then T // compiler which is not supporting partial ordering will decide that f((int*)0) // is ambiguous. We must resolve the ambiguity our self. // There is more then one way of doing it but I like the following: // struct A{}; // struct B : A{}; // template void f(T, A); // template void f(T*, B); // template void f(T x) { f(x, B()); } // for pointers f(T*, B) is better then f(T, A) when the call is f(ptr, B()); // // // This template will help us to "order" the function templates. // template struct Order : Order {}; template<> struct Order<0> {}; template struct TypeTag { typedef char (&X)[I]; }; // // This template class simulate the detection of the best specialization // template class AppendPattern { // you can call me insane but VC7 fails without the following typedefs typedef TypeTag<2>::X X2; typedef TypeTag<3>::X X3; typedef TypeTag<4>::X X4; // Match Append static TypeTag<1>::X Match(Type2Type, Type2Type, Order<1>); // Match Append template static TypeTag<2>::X Match(Type2Type, Type2Type, Order<0>); // Match Append> template static TypeTag<3>::X Match(Type2Type, Type2Type >, Order<1>); // Match Append, T> template static TypeTag<4>::X Match(Type2Type >, Type2Type, Order<0>); static Type2Type Get1(); static Type2Type Get2(); // VC will fail if the sizeof is written directly to the TypeTag enum { value = sizeof(Match( Get1(), Get2(), Order<1>() )) }; public: typedef TypeTag Result; }; template class Append2; // // This template class simulate the detection of the partial specialization // The append helper simulate the partial specialized class templates with // explicit specialization that represent the selected specialization and // nested class template which implement the specialization // template struct AppendHelper; template<> struct AppendHelper< TypeTag<1> > { // Append template struct In { typedef NullType Result; }; }; template<> struct AppendHelper< TypeTag<2> > { // Append template struct In { typedef TYPELIST_1(T) Result; }; }; template<> struct AppendHelper< TypeTag<3> > { // Append > template struct In { typedef typename TList::Head Head; typedef typename TList::Tail Tail; typedef Typelist Result; //typedef TList Result; }; }; template<> struct AppendHelper< TypeTag<4> > { // Append, T> template struct In { typedef typename TList::Head Head; typedef typename TList::Tail Tail; typedef Typelist::Result> Result; }; }; template class Append2 { // First we detect the best specialization typedef typename AppendPattern::Result Pattern; public: // Insatiate the best specialization typedef typename AppendHelper:: template In::Result Result; }; // // Lets toy with the simulated Append // typedef struct IncompType *IncompPtr; struct A1 {}; struct B1 : A1 {}; struct A2 {}; struct B2 : A2 {}; struct C1 : B1 {}; struct C2 : B2 {}; struct D1 : C1, C2 {}; namespace { template struct PrintTypelist { PrintTypelist() { typedef typename TList::Head Head; typedef typename TList::Tail Tail; printf("%s ,", typeid(Head).name()); PrintTypelist(); } }; template<> struct PrintTypelist { PrintTypelist() { printf("\n"); } }; template void Test_Append2() { typedef typename TL::Append::Result typelist1_t; typedef typename Append2::Result typelist2_t; // Assert (compile time) that typelist1_t and typelist2_t are the same type STATIC_CHECK((Conversion::sameType), Append2_Failed); PrintTypelist(); PrintTypelist(); } void Test_Append() { typedef TL::MakeTypeList::Result typelist1_t; typedef TL::MakeTypeList::Result typelist2_t; Test_Append2(); Test_Append2(); Test_Append2(); Test_Append2(); Test_Append2(); Test_Append2(); } } // anonymous namespace int main() { Test_Append(); system("pause"); }