Keyword typename:
template <typename T>
class MyClass {
typename T::SubType * ptr;
...
};
Now keyword typename is very important in the declaration above and is required otherwise compiler will treat T::SubType * ptr as multiplication of static member SubType inside T with ptr; T being generic type , it is programmer's job to tell compiler that SubType is a type inside T.
so with typename the declaration means ptr is a pointer of SuyType.
typename T::SubType * ptr;
...
};
Now keyword typename is very important in the declaration above and is required otherwise compiler will treat T::SubType * ptr as multiplication of static member SubType inside T with ptr; T being generic type , it is programmer's job to tell compiler that SubType is a type inside T.
so with typename the declaration means ptr is a pointer of SuyType.
Template template parameters
template t<typename T, typename Container>
class Stack {...}; //declaration
Stack<int, std::vector<int> > vStack; //stack of int using vector as container.
can this be written as
Stack<int, std::vector> > vStack;
To do this template declaration changes as follows. Following applies to class templates only.
template <typename T, template< typename ELEM> class CONT = std::deque>
class Stack { ... };
Now in the code above second template parameter is a class template
template < typename ELEM > class CONT //and is defaulted to std::deque.
which effectively declare container as std::deque<ELEM> but what we want is std::deque<T>
so ELEM is not used hence we can ignore the type and modify the declaration as follows, that way same type T is used for std::deque.
template < typename T, template <typename> class CONT = std::deque>
class Stack{ ... };
//member functions change accordingly
template <typename T, template< typename> class CONT>
Stack<T,CONT>::push(const T& elem)
{
elems.push_back(elem);
}
template <typename T, template<typename> typename CONT = std::deque>
class Stack {...}; //ERROR
//previous declaration:
template <typename T, template<typename> class CONT = std::deque>
class Stack {...}; //CORRECT
we replaced the word class with typename with class and that is an error because, this word class indicates that it is a class template or second template param of Stack is a class template. i.e. std::deque or any container for that matter is a class template hence the key word class is used as in a C++ class.
class Stack {...}; //declaration
Stack<int, std::vector<int> > vStack; //stack of int using vector as container.
can this be written as
Stack<int, std::vector> > vStack;
To do this template declaration changes as follows. Following applies to class templates only.
template <typename T, template< typename ELEM> class CONT = std::deque>
class Stack { ... };
Now in the code above second template parameter is a class template
template < typename ELEM > class CONT //and is defaulted to std::deque.
which effectively declare container as std::deque<ELEM> but what we want is std::deque<T>
so ELEM is not used hence we can ignore the type and modify the declaration as follows, that way same type T is used for std::deque.
template < typename T, template <typename> class CONT = std::deque>
class Stack{ ... };
//member functions change accordingly
template <typename T, template< typename> class CONT>
Stack<T,CONT>::push(const T& elem)
{
elems.push_back(elem);
}
'typename' or 'class'
one would argue that above declaration can be written something liketemplate <typename T, template<typename> typename CONT = std::deque>
class Stack {...}; //ERROR
//previous declaration:
template <typename T, template<typename> class CONT = std::deque>
class Stack {...}; //CORRECT
we replaced the word class with typename with class and that is an error because, this word class indicates that it is a class template or second template param of Stack is a class template. i.e. std::deque or any container for that matter is a class template hence the key word class is used as in a C++ class.
Initialising member types of type T ( generic type)
To make sure that a member of a class template, for which the type is parameterized, gets initialized, you have to
define a default constructor that uses an initializer list to initialize the member:
template <typename T> class MyClass {
private: T x;
public:
MyClass() : x() { // ensures that x is initialized even for built-in types }
...
};
Using string literals in as template params
template <typename T> class MyClass {
private: T x;
public:
MyClass() : x() { // ensures that x is initialized even for built-in types }
...
};
Using string literals in as template params
// note: reference parameters
template <typename T>
inline T const& max (T const& a, T const& b) {
return a < b ? b : a; }
int main()
{
std::string s;
::max("apple","peach"); //OK same type
::max("apple","tomato"); // ERROR: different types ::max("apple",s);
// ERROR: different types
}
here type of "apple" is char const[6] and that of tomato is char const[7] hence they are different type. solution is to call them using
::max(std::string("apple"), std::string("tomato")); // now types are same.
or alternatively max can be defined without using references as follows
template <typename T>
inline T const& max (T const& a, T const& b) {
return a < b ? b : a; }
int main()
{
std::string s;
::max("apple","peach"); //OK same type
::max("apple","tomato"); // ERROR: different types ::max("apple",s);
// ERROR: different types
}
here type of "apple" is char const[6] and that of tomato is char const[7] hence they are different type. solution is to call them using
::max(std::string("apple"), std::string("tomato")); // now types are same.
or alternatively max can be defined without using references as follows
// note: nonreference parameters
template <typename T> inline T max (T a, T b)
{
return a < b ? b : a;
}
int main()
{
template <typename T> inline T max (T a, T b)
{
return a < b ? b : a;
}
int main()
{
std::string s;
::max("apple","peach"); // OK: same type
::max("apple","tomato"); // OK: to same type
::max("apple",s); // ERROR: different types
}
For more information refer the book.
::max("apple","tomato"); // OK: to same type
::max("apple",s); // ERROR: different types
}
For more information refer the book.