#ifndef _TEMPLATE_WIZARDRY_H #define _TEMPLATE_WIZARDRY_H template struct _selectLR{}; template struct _selectLR<0,T,U>{ typedef T Type; }; template struct _selectLR<1,T,U>{ typedef U Type; }; template struct _equal{ enum { value = 0 }; }; template struct _equal{ enum { value = 1 }; }; template struct intEq{ static const bool val = false; }; template struct intEq{ static const bool val = true; }; template struct my_enable_if{}; template struct my_enable_if{ typedef T type; }; template struct is_double_or_float{ enum {value = 0}; }; template<> struct is_double_or_float{ enum {value = 1}; }; template<> struct is_double_or_float{ enum {value = 1}; }; //A method of asking whether a type is an std::complex or std::complex template struct is_complex_double_or_float{ enum {value = 0}; }; template<> struct is_complex_double_or_float >{ enum {value = 1}; }; template<> struct is_complex_double_or_float >{ enum {value = 1}; }; #ifdef USE_GRID //A method of asking a Grid vector type if it's scalar_type is complex, predicated on whether the type is indeed a Grid vector type template struct is_scalar_type_complex{}; template struct is_scalar_type_complex{ //safe to call scalar type enum {value = Grid::is_complex::value }; }; template struct is_scalar_type_complex{ enum {value = 0}; }; //A method of asking whether a type is a Grid *complex* vector type template struct is_grid_vector_complex{ enum {value = is_scalar_type_complex::value, T>::value }; }; #else template struct is_grid_vector_complex{ enum {value = 0}; }; #endif //A method of providing a list of conditions and associated types for classification struct no_mark{}; template struct TestElem{}; template struct TestElem{ typedef IfTrue type; }; template struct TestElem{ typedef typename NextTest::type type; }; struct LastElem{ typedef no_mark type; }; //An expandable method of classifying a complex type struct complex_double_or_float_mark{}; struct grid_vector_complex_mark{}; template struct ComplexClassify{ typedef typename TestElem< is_complex_double_or_float::value, complex_double_or_float_mark, TestElem< is_grid_vector_complex::value, grid_vector_complex_mark, LastElem> >::type type; }; //A version of is_base_of (copied from the internet! https://stackoverflow.com/questions/2910979/how-does-is-base-of-work) template struct _is_base_of_host { operator B*() const; operator D*(); }; template struct my_is_base_of { template static char check(D*, T); static std::pair check(B*, int); static const bool value = sizeof(check(_is_base_of_host(), int())) == sizeof(char); }; //Generate a test for if a class has an enum with a particular name #define define_test_has_enum(ENUM) \ template \ struct has_enum_##ENUM{ \ typedef char yes; \ typedef yes (&no)[2]; \ \ template \ struct test2; \ \ template \ static yes test(test2*); \ template \ static no test(...); \ \ static bool const value = sizeof(test(0)) == sizeof(yes); \ } //Example usage: // // define_test_has_enum(HELLO); // struct Astruct{ // enum { HELLO=0 }; // }; // struct Bstruct{ // }; // // // assert( has_enum_HELLO::value == true ); // assert( has_enum_HELLO::value == false ); //A method of using compound templated classes and recursive functions to iterate over types in a static list struct ListEnd{}; template struct Elem{ typedef V ValueType; typedef N NextType; }; //Get a type by index template struct getTypeFromList{ typedef typename getTypeFromList::type type; }; template struct getTypeFromList{ typedef typename TypeList::ValueType type; }; //A struct containing instances of the list of types. template struct ListStruct{ typedef typename TypeList::ValueType ValueType; typedef ListStruct NextType; ValueType v; NextType n; ListStruct(){} ListStruct(const ListStruct &r): v(r.v),n(r.n){} }; template<> struct ListStruct{}; //Access elements by compile time index template struct getConstElemFromListStruct{ static inline const typename getTypeFromList::type & get(const aListStruct &from){ return getConstElemFromListStruct::get(from.n); } }; template struct getConstElemFromListStruct{ static inline const typename aListStruct::ValueType & get(const aListStruct &from){ return from.v; } }; template struct getElemFromListStruct{ static inline typename getTypeFromList::type & get(aListStruct &from){ return getElemFromListStruct::get(from.n); } }; template struct getElemFromListStruct{ static inline typename aListStruct::ValueType & get(aListStruct &from){ return from.v; } }; //Number of elements in ListStruct template struct getSizeOfListStruct{ enum{ value = getSizeOfListStruct::value }; }; template struct getSizeOfListStruct, count>{ enum{ value = count }; }; //Example print all elements template struct _printAll{ static void doit(std::ostream &into, const aListStruct &src){ into << src.v << '\n'; typedef typename aListStruct::NextType Next; _printAll::doit(into,src.n); } }; template<> struct _printAll< ListStruct >{ static void doit(std::ostream &into, const ListStruct &src){ } }; //Example print single element template struct _printElement{ static void doit(std::ostream &into, const aListStruct &src){ typedef typename aListStruct::NextType Next; _printElement::doit(into,src.n); } }; template struct _printElement{ static void doit(std::ostream &into, const aListStruct &src){ into << src.v << '\n'; } }; //Perform an operation with templated parameter and static member 'doit' on all elements of list template< template class Operation, typename aListStruct> struct _operationAll{ static void doit(const aListStruct &src){ typedef typename aListStruct::ValueType ValueType; typedef typename aListStruct::NextType NextType; Operation::doit(src.v); _operationAll::doit(src.n); } }; template< template class Operation> struct _operationAll >{ static void doit(const ListStruct &src){ } }; //An example operation template struct _printcout{ static void doit(const T &src){ std::cout << src << '\n'; } }; #endif