www.pudn.com > Loki.rar > Simulate_PS.cpp


// 
// 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 "Typelist.h" 
#include "static_check.h" 
 
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(); 
}