C ++ template meta-programming Chapter 2 exercise questions
2-0. Write a single dollar function add_const_ref If T is a reference type, T is returned; otherwise, T is returned.
Const &. Compile a program to test your functions. Tip: You can use boost: is_same to test the result.
This is relatively simple:
template
struct add_const_ref{typedef T const& type;};template
struct add_const_ref
{typedef T& type;};
Test code:
void fun_add_const_ref(){typedef const int Cint;typedef const int& CRint;typedef int& Rint;if (boost::is_same
::type>::value){std::cout << "true\n\n";}else{std::cout << "false\n\n";}if (boost::is_same
::type>::value){std::cout << "true\n\n";}{std::cout << "false\n\n";}}
2-1. Compile a ternary metafunction replace_type It receives any Composite Type c as its first parameter,
Replace all types x in c with y:
Typedef replace_type <void *, void, int>: type t1; // int *
Typedef replace_type <
Int const * [10]
, Int const
, Long
>:: Type t2; // long * [10]
Typedef replace_type <
Char & (*) (char &)
, Char &
, Long &
>:: Type t3; // long & (*) (long &)
You can limit the type of the function to a function with less than two parameters.
This is complicated:
Solution in four steps
1. first determine whether c contains Type x
2. If there is a replacement
3. If no value is found, the meta type is returned.
4. Special template features
template
struct is_same: boost::mpl::bool_
{};//#1template
struct is_same
: boost::mpl::bool_
{};//#1template
struct replace_type_imp;//#2template
struct replace_type{static bool const value = is_same
::value;//#3typedef typename replace_type_imp
::type type;//#4};
#1 determine whether two types are of the same type. If true is returned, otherwise false is returned.
# 2replace_type specific implementation, including a special situation
#3 return results with the same value
#4 return type based on vlaue Value
The following is a general implementation:
/// Special void // TC: void const *, TX: void consttemplate
Struct replace_type_imp
{Typedef typename replace_type
: Type () ;}; // special TC * // TC: int const *, TX: int consttemplate
Struct replace_type_imp
{Typedef typename replace_type
: Type * type;}; // special TC & // TC: int const &, TX: int consttemplate
Struct replace_type_imp
{Typedef typename replace_type
: Type & type ;}; // special TC [] // TC: int const [], TX: int consttemplate
Struct replace_type_imp
{Typedef typename replace_type
: Type [] ;}; // special TC [N] // TC: int const [N], TX: int consttemplate
Struct replace_type_imp
{Typedef typename replace_type
: Type [N];};
Special Functions
// Accept a parameter // TC: char * (*) (char *), TX: char *, TY: inttemplate
Struct replace_type_imp
{Typedef typename replace_type
: Type (typename replace_type: type); // #1 // # How can I define a function pointer at 1}; // accept two parameters // TC :: char * (*) (char *, const char *), TX: char *, TY: inttemplate
Struct replace_type_imp
{Typedef typename replace_type
: Type (typename replace_type: type, typename replace_type: type) ;}; // three function templates are accepted.
Struct replace_type_imp
{Typedef typename replace_type
: Type (typename replace_type: type, typename replace_type: type, typename replace_type: type) ;}; //... accept any more parameters
Value is true:
template
struct replace_type_imp
{typedef TY type;};
Final Test
void fun_is_same(){typedef char& (*FunPoint[])(char&);typedef char& Rchar;typedef const int v1;typedef const int v2;typedef int* v3;typedef int* (*IntPoint[])(int*);if (is_same
::value) std::cout << "same\n\n";else std::cout << "false\n\n" << std::endl;if (boost::is_same
::value) std::cout << "same\n\n";else std::cout << "false\n\n" << std::endl;typedef replace_type
::type v4;if (is_same
::value) std::cout << "same\n\n";else std::cout << "false\n\n" << std::endl;if (boost::is_same
::value) std::cout << "same\n\n";else std::cout << "false\n\n" << std::endl;typedef replace_type
::type v5;if (is_same
::value) std::cout << "same\n\n";else std::cout << "false\n\n" << std::endl;if (boost::is_same
::value) std::cout << "same\n\n";else std::cout << "false\n\n" << std::endl;typedef replace_type
::type v6;if (is_same
::value) std::cout << "same\n\n";else std::cout << "false\n\n" << std::endl;if (boost::is_same
::value) std::cout << "same\n\n";else std::cout << "false\n\n" << std::endl;}
2-2. boost: polymorphic_downcast
Function Template
Implement a static_cast with check version to point to Polymorphism
Downward transformation of object pointers:
Template Inline Target polymorphic_downcast (Source * x)
{
Assert (dynamic_cast (X) = x );
Return static_cast (X );
}
In the released software, assertion disappears and polymorphic_downcast can be as efficient as the simple static_cast. Use the type traits facility to compile a template implementation product so that it can receive both pointer parameters and reference parameters:
Struct A {virtual ~ A (){}};
Struct B: {};
B B;
A * a_ptr = & B; B * B _ptr = polymorphic_downcast (A_ptr); A & a_ref = B;
B & B _ref = polymorphic_downcast (A_ref );
This question is not understood and will not be done ~~~~~~
2-3. Use type traits
The Facility implements a type_descriptor class template. When it is streamed, its instance prints
The template parameter type:
Std: cout < (); // Print "char *";
Std: cout < (); // Print "longconst *&";
You can assume that the template parameters of type_descriptor are limited
Composite types constructed based on the following four integer types: char, short int, int, and long int.
This question is relatively simple, but you do not need to paste the Code directly:
template
struct get_description{static std::string value;operator const char*(){return value.c_str();}};template
std::string get_description
::value = "can not deduce the type";template<>std::string get_description
::value = "int";template<>std::string get_description
::value = "char";template<>std::string get_description
::value = "short";template<>std::string get_description
::value = "long";template<>std::string get_description
::value = "float";template<>std::string get_description
::value = "double";template
struct get_description
{operator const char*(){static std::string ret = get_description
();ret += " const";return ret.c_str();}};template
struct get_description
{operator const char*(){static std::string ret = get_description
();ret += " *";return ret.c_str();}};template
struct get_description
{operator const char* (){static std::string ret = get_description
();ret += " &";return ret.c_str();}};
Test code:
void fun_type_descriptor(){std::cout << get_description
() << std::endl;std::cout << get_description
()<< std::endl;//std::cout << get_description
()<< std::endl;}
2-5. Modify type_descriptor in Exercise 2-3
Template to output the type pseudo-English description, just like the cdecl Program
What the explain command does:
// Print "array of pointer to function returning pointer to char"
Std: cout <type_descriptor <char * (* [])> ();
This question is also relatively simple and can be directly written to the Code:
template
struct get_description{static std::string value;operator const char*(){return value.c_str();}};template
std::string get_description
::value = "can not deduce the type";template<>std::string get_description
::value = "int";template<>std::string get_description
::value = "char";template<>std::string get_description
::value = "short";template<>std::string get_description
::value = "long";template<>std::string get_description
::value = "float";template<>std::string get_description
::value = "double";template
struct get_description
{operator const char*(){static std::string ret = get_description
();ret += " const";return ret.c_str();}};template
struct get_description
{operator const char*(){static std::string ret = get_description
();ret += " volatile";return ret.c_str();}};template
struct get_description
{operator const char*(){static std::string ret = "pointer to ";ret += get_description
();return ret.c_str();}};template
struct get_description
{operator const char* (){static std::string ret = "reference to ";ret += get_description
();return ret.c_str();}};template
struct get_description
{operator const char* (){std::cout << typeid(T).name() << "\n";static std::string ret = "array of ";ret += get_description
();std::cout << typeid(T).name() << "\n";return ret.c_str();}};template
struct get_description
{operator const char* (){std::cout << typeid(T).name() << "\n";static std::string ret = "array of ";ret += get_description
();std::cout << typeid(T).name() << "\n";return ret.c_str();}};template
struct get_description
{operator const char* (){static std::string ret = "pointer to function returning ";ret += get_description
();return ret.c_str();}};template
struct get_description
{operator const char* (){static std::string ret = "this is a pointer function with ";ret += get_description();ret += " and it pointer to function returning ";ret += get_description
();return ret.c_str();}};template
struct get_description
{operator const char* (){std::cout << typeid(T).name() << "\n";static std::string ret = "pointer to function with ";ret += get_description();ret += " returning ";ret += get_description
();std::cout << typeid(T).name() << "\n";return ret.c_str();}};template
struct get_description
{operator const char* (){std::cout << typeid(T).name() << "\n";static std::string ret = "this is a pointer function with ";ret += get_description();ret += " and it pointer to function with ";ret += get_description();ret += " returning ";ret += get_description
();std::cout << typeid(T).name() << "\n";return ret.c_str();}};
Test code:
void fun_text_descriptor(){//std::cout << get_description
() << std::endl;typedef int (*FunPoint[10])(char*);std::cout << get_description
()<< std::endl;std::cout << get_description
() << std::endl;}
Now we have done these questions !!!!