C++ Templates (Pt.2)
C. Papachristos
Robotic Workers Lab
University of Nevada, Reno
CS-202
Course , Projects , Labs:
Your 10th Project will be announced today Thursday 4/23.
9th Project Deadline was this Wednesday 4/22.
Course Week
CS-202 C. Papachristos
Monday | Tuesday | Wednesday | Thursday | Friday | | Sunday |
|
|
| Lab (8 Sections) |
| | |
| CLASS | PASS Session | CLASS |
| | |
PASS Session | | Project DEADLINE | NEW Project | PASS Session | | PASS Session |
Today’s Topics
CS-202 C. Papachristos
Template Specialization
Class Template friend(s)
Template(s) and Names
The Standard Template Library
std::vector
std::list , std::forward_list
std::set , std:: multiset
std::pair
std::set , std::multiset
std::map , std::multimap
Template(s)
CS-202 C. Papachristos
Function Overloads and Templates
A (misbehaving) Function Template
char const * s1 = "abcd";
char const * s2 = "XYZW";
cout << Max( s1, s2 );
The compiler generates:
char const * Max (char const * const & a, char const * const & b){� if ( a < b ) � return b;
else � return a;�}
Will try to sort them by their Memory Address.
template < typename T >
T Max(T const & v1, T const & v2){
if (v1 < v2) return v2;
else return v1;
};
Remember: As we have mentioned on how to backwards-read these:�char const * “Pointer to Constant Character”
const char * “Pointer to Character that is Constant”
(They are the same const-qualified Pointer-Type declarations)
(Possible) Output: XYZW
Template(s)
CS-202 C. Papachristos
Function Overloads and Templates
Function Overloads vs Function Templates.
The compiler will “prefer” this instead of the Function Template version.
char const * Max(char const * a, char const * b)
{
if (strcmp(a, b) < 0)
return b;
else
return a;
}
Function Overload�has precedence over Function Template.
Template(s)
CS-202 C. Papachristos
Function Overloads and Templates
Function Overloads vs Function Templates.
char const * s1 = "abcd";
char const * s2 = "XYZW";
cout << Max( s1, s2 );
template < typename T >
T Max(T const & v1, T const & v2){
if (v1 < v2) return v2;
else return v1;
};
char * Max(char * a, char * b) {
if (strcmp(a, b) < 0)
return b;
else
return a;
}
This Overload is NOT a match!
char const * Max (char const * const & a,
char const * const & b) {� if ( a < b ) � return b;
else � return a;�}
So the compiler will still resort to the Template !
Template(s)
CS-202 C. Papachristos
The keyword template
Function template(s) Specialization.
Function Template Specialization.
Syntax A) – Implicit Type Deduction:
template < >
return-type TplFunc(params){ … }
Syntax B) – Explicit Type Deduction:
template < >
return-type TplFunc<Specific-Types>(params){ … }
template < typename T >
void Swap(T & v1, T & v2)
{
T temp=v1; v1=v2; v2-temp;
};
template < >
void Swap(char & v1, char & v2)
{
if ((v1…a-Z) && (v2…a-Z)){
char temp=v1;
v1=v2; v2-temp;
}
};
char–Specialized� Function Swap�Template
Function
Swap
Template
Template(s)
CS-202 C. Papachristos
The keyword template
Function template(s) Specialization.
Partial Specialization → Refers to a modifier of T.
Syntax:
template < typename T >
T-mod-return TplFunc(T-mod-params)�{ … }
template < typename T >
T Max(T const & v1,
T const & v2){
return (v1 < v2)? v2:v1;
};
template < typename T >
T * Max(T * const & v1,
T * const & v2){
return (*v1 < *v2)? v2:v1;
};
Pointer–Specialized� Function Max�Template
Note: Formally Function Templates are not Partially Specializing, they Overload.
Function
Max
Template
Template(s)
CS-202 C. Papachristos
The keyword template
Function template(s) Specialization.
const char * s1 = "abcd";
const char * s2 = "XYZW";
cout << Max(s1, s2);
template < typename T >
T Max(const T & v1,
const T & v2){
return (v1 < v2)? v2:v1;
};
char const * Max(char const * const & v1,
char const * const & v2)
{
return (v1 < v2)? v2:v1;
};
Compiler-made
Direct Template�use with char *
Function
Max
Template
Function Instantiation from Template
Template(s)
CS-202 C. Papachristos
The keyword template
Function template(s) Specialization.
const char * s1 = "abcd";
const char * s2 = "XYZW";
cout << Max(s1, s2);
Note:
Partial Specialization for Pointer-modifier�of T is necessary, otherwise the Explicit�Specialization will not find an appropriate function definition.
template < typename T >
T Max(T const & v1,T const & v2){
return (v1 < v2) ? v2:v1;
};
template < typename T >
T const * Max(T const * const & v1,
T const * const & v2)
{
return (*v1 < *v2) ? v2:v1;
};
const-Pointer
Specialized� Function Max�Template
template < >
char const * Max(char const * const & v1,
char const * const & v2)
{
int res = strcmp(v1,v2);
return !res ? NULL : (res<0?v1:v2);
};
char *–Specialized� Function Max�Template
Function
Max
Template
Template(s)
CS-202 C. Papachristos
The keyword template
Function template(s) Specialization.
const char * s1 = "abcd";
const char * s2 = "XYZW";
cout << Max(s1, s2);
char const * Max(char const * v1,
char const * v2)
{
return strcmp(v1,v2) ? v2:v1;
};
Simpler:�char const *–Overloaded Function Max
template < typename T >
T Max(T const & v1,T const & v2){
return (v1 < v2) ? v2:v1;
};
Function
Max
Template
Template(s)
CS-202 C. Papachristos
The keyword template
Function template(s) Specialization (Advanced)
A non Explicitly-Templated call of a function.
void func(int *);
b) If no such match is found, Base-Templates (ones with Type) are queried, and the “most specialized” will be used:
template<typename T> (a) A Base-Template
void func( T ){ … }
template<typename T> (b) A second Base-Template,
void func( T * ){ … } (Partially-Specializes/) Overloads (a)
template <> (c) Explicit Specialization of (b)
void func(int *){ … }
int * int_Pt;
func( int_Pt );
template<typename T> (a) A Base-Template
void func( T ){ … }
template <> (c) Explicit Specialization of (a)
void func(int *){ … }
template<typename T> (b) A second Base-Template,
void func( T * ){ … } (Partially-Specializes/) Overloads (a)
The more specialized (the one that gets called).
Compiler will perform: 1st Overload Resolution
2nd Specialization Lookup
Template(s)
CS-202 C. Papachristos
The keyword template
Class template(s) Specialization.
Class Template Specialization.
Syntax:
template < >
class TplClass < special-type >�{ … }
template < typename T >
class Buffer {
public:
Buffer(); …
private:
T m_array[ARRAY_MAX];
int m_size;
};
template < >
class Buffer < char > {
public:
Buffer(); …
private:
char m_array[STRLEN_MAX];
int m_strLength;
};
char–specialized� Class Buffer�Template
Class
Buffer
Template
Template(s)
CS-202 C. Papachristos
The keyword template
Function With Class Template Parameters.
template < typename T >
void Sort( ArrayContainer< T > arrayContainer ){
for (…){
if ( arrayContainer[…] < arrayContainer[…] )
arrayContainer[…] = …;
}
}
Template(s)
CS-202 C. Papachristos
The keyword template
Class friend(s) & template(s).
template < typename T >
class ArrayContainer {
public:
ArrayContainer(); …
friend ostream & operator<<(ostream& os, const ArrayContainer<T> & a);
private:
T * m_arr; …
};
warning: friend declaration 'std::ostream& operator<<(std::ostream&, const ArrayContainer<T>&)' declares a non-template function [-Wnon-template-friend]
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
undefined reference to `operator<<(std::ostream&, ArrayContainer<int> const&)'
Compilation proceeds with warnings.
Linking fails.
BUT they might need�to be Templates too !
Template(s)
CS-202 C. Papachristos
The keyword template
Class friend(s) & template(s).
template < typename T >
class ArrayContainer {
public:
ArrayContainer(); …
friend ostream & operator<< <> (ostream& os, const ArrayContainer<T> & a);
private:
T * m_arr; …
};
template < typename T >
ostream& operator<< (ostream & os, const ArrayContainer<T> & a)
{ for (…){ os << a[i]; } … return os; }
Declares the operator<< Function Template specialization (for�the particular T) as a friend.
BUT they might need�to be Templates too !
Template(s)
CS-202 C. Papachristos
The keyword template
Class friend(s) & template(s).
template<typename T> class ArrayContainer;
template<typename T> ostream & operator<< (ostream & os, const ArrayContainer<T> & a);
template < typename T >
class ArrayContainer {
public:
ArrayContainer(); …
friend ostream & operator<< <> (ostream & os, const ArrayContainer<T> & a);
private:
T * m_arr; …
};
template < typename T >
ostream & operator<< (ostream & os, const ArrayContainer<T> & a){
for (…){ os << a[i]; } …
return os;
}
Forward Declarations
Class Template
Function Implementation
Template(s)
CS-202 C. Papachristos
The keyword template
Class friend(s) & template(s).
template < typename T >
class ArrayContainer {
public:
ArrayContainer(); …
friend ostream & operator<< (ostream & os, const ArrayContainer<T> & a)
friend ostream & operator<< (ostream & os, const ArrayContainer & a)
{
for (…){ os << a[i]; }
return os;
}
private:
T * m_arr; …
};
Inline Declaration inside Templated Class Body generates�a separate non-templated operator<< for each T and makes it a friend of its ArrayContainer<T>.
or
Template(s)
CS-202 C. Papachristos
The keywords template and typename
Name(s) and template(s).
Qualified / Unqualified Names
std:: cout << "Hello World! " << std:: endl ;
Objects’ Names cout and endl are Qualified (in the namespace std).
Template(s)
CS-202 C. Papachristos
The keywords template and typename
Name(s) and template(s).
Qualified / Unqualified Names
std:: cout << "Hello World! " << std:: endl ;
using namespace std;
cout << "Hello World!" << endl ;
using directive introduces Names into the Namespace scope that it appears in (same as using std::cout; using std::endl;).
Template(s)
CS-202 C. Papachristos
The keywords template and typename
Name(s) and template(s).
Qualified / Unqualified Names
std:: cout << "Hello World! " << std:: endl ;
using namespace std;
cout << "Hello World!" << endl ;
Note: Still Qualified names, despite introducing std names into global scope.
using namespace std;
std::cout << "Hello World!" << std::endl ;
Template(s)
CS-202 C. Papachristos
The keywords template and typename
Name(s) and template(s).
Dependent Names
template < typename T >
class MotionPlan : public List< T >
{
MotionPlan() : m_total( List<T>::total_num )
{ }
void AdvanceWaypoint(List< T > * l)
{ l -> m_wp ++; }
const int m_total;
typename List< T >::Waypoint m_wp;
};
List<T> is Dependent on T: (CityName, GeoReferencedCoordinate, CheckerboardSquare …)
Template(s)
CS-202 C. Papachristos
The keywords template and typename
Name(s) and template(s).
Dependent Names
template < typename T >
class MotionPlan : public List< T >
{
MotionPlan() : m_total( List<T>::total_num )
{ }
void AdvanceWaypoint(List< T > * l)
{ l -> m_wp ++; }
const int m_total;
typename List< T >::Waypoint m_wp;
};
A Member of the Templated Class l�whose instantiation is dependent on T: (raw pointer, index, iterator…)
Template(s)
CS-202 C. Papachristos
The keywords template and typename
Name(s) and template(s).
Dependent Names
template < typename T >
class MotionPlan : public List< T >
{
MotionPlan() : m_total( List<T>::total_num )
{ }
void AdvanceWaypoint(List< T > * l)
{ l -> m_wp ++; }
const int m_total;
typename List< T >::Waypoint m_wp;
};
A Type whose instantiation
is Dependent on T.
template < typename T >
class List
{
static const int total_num = … ;
typedef T* Waypoint;
};
Template(s)
CS-202 C. Papachristos
The (keyword) typename Disambiguator
Disambiguation of Dependent & Qualified Names:
template < typename T >
void sort_local(){
ArrayContainer< T > :: Accessor ac;
ac.moveToBeginning(); T data = ac.accessData();
ac.moveForward(); T data = ac.accessData();
…
}
C++ Standard (14.6/2): “A name used in a template declaration or definition and that is� dependent on a template-parameter is assumed not to name a type unless the applicable� name lookup finds a type name or the name is qualified by the keyword typename.”
Compiler will attempt to interpret this as a variable.
When instantiating code employing Names that are Qualified and Dependent�the Compiler needs to know T is used as part of a Type name, as the Standard demands early checking�to be enabled (otherwise Accessor can be the name of a Member or a nested Type, and we would have�to wait until T is known to perform any checks.
Template(s)
CS-202 C. Papachristos
The (keyword) typename Disambiguator
Disambiguation of Dependent & Qualified Names:
template < typename T >
void sort_local(){
ArrayContainer< T > :: Accessor ac;
typename ArrayContainer< T > :: Accessor ac;
ac.moveToBeginning(); T data = ac.accessData();
ac.moveForward(); T data = ac.accessData();
…
}
Template(s)
CS-202 C. Papachristos
The (keyword) template Disambiguator
Disambiguation of Explicitly Qualified Template Member(s):
class TplMethodClass {
public: …
template<typename T>
T tpl_member_func();
};
template < typename U >
void func( U arg )
{
int obj =
arg . template tpl_member_func<int>();
}
ISO C++03 14.2/4 :
When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id�explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.
Note: Otherwise the compiler can’t know early on whether the upcoming symbol < is a less-than operator or the beginning of a template parameters list.
STL
CS-202 C. Papachristos
The Standard Template Library
A library of C++ very useful classes and functions that were developed over time and are now part of the C++ Standard Library.
The STL contains many useful things, including:
Store Data and maintain Data Association.
Provide Higher-level Data Structure interfaces but can rely on different Container back-ends.
Access & Manipulation of Data.
All are Function & Class Templates !
STL
CS-202 C. Papachristos
The Standard Template Library
A library of C++ very useful classes and functions that were developed over time and are now part of the C++ Standard Library.
The STL provides Re-usable code:
linked list, vector, map, multi-map, pair, set, multi-set, queue, stack, etc …
We usually have many more things to do than re-inventing the wheel ...
STL
CS-202 C. Papachristos
STL Containers
All containers implemented in the form of multilayered Class Templates.
They all provide interfaces for some common basic operations:
Note:
std::size_t is the type of any sizeof expression and is guaranteed to be able to express:
for ( std::size_t i = 0; i<…; ++i){ … }
Check if container is empty.
Mark the container as empty, and deallocate data if necessary.
Return number of elements in the container.
STL
CS-202 C. Papachristos
STL Containers
Vector(s) ( std::vector< … > )
Basic attributes:
Using:
T & operator[](std::size_t pos);
T & at(std::size_t pos);
Access element at position pos (without bounds checking).
Access element at position pos�(throws a std::out_of_range Exception�if !(pos < size())).
Both return Reference (not Pointer) to requested element.
STL
CS-202 C. Papachristos
STL Containers
Vector(s) ( std::vector< … > )
Basic functions:
Access first and last element in the container.
Push element to last position (back) or remove last element (back).
Insert or erase element in any position within the container (iterator-based method).
Resize container to fit size number of elements.
STL
CS-202 C. Papachristos
STL Containers
Linked-List(s) ( std::list< … > , std::forward_list< … > )
Basic attributes:
Basic functions:
STL
CS-202 C. Papachristos
STL Containers
Set(s) ( std::set< … > )
Basic attributes – Unique Keys :
Basic functions:
Note:
Uses Equivalence checking (via the Compare function) to find matching Key key from the Set.
STL
CS-202 C. Papachristos
STL Containers
Multiset(s) ( std::multiset< … > )
Basic attributes – Multiple Key Entries :
Basic functions:
Note:
Uses Equivalence checking.
STL
CS-202 C. Papachristos
STL Containers
Pair(s) ( std::pair< …,… > )
Basic attributes:
T1 first;
T2 second;
Basic functions:
int racePosition = 1;
Car myCar("Gandalf");
std::pair<int, Car> racecar;
racecar.first = racePosition;
racecar.second = myCar;
std::pair<int, Car> racecar = std::make_pair(racePosition, myCar);
STL
CS-202 C. Papachristos
STL Containers
Map(s) ( std::map< …,… > )
Basic attributes – Unique Keys :
Basic functions:
Note:
Uses Equivalence checking (via Compare) to find matching Key key.
STL
CS-202 C. Papachristos
STL Containers
Multimap(s) ( std::multimap< …,… > )
Basic attributes – Multiple Key Entries :
Basic functions:
Note:
Uses Equivalence checking.
STL
CS-202 C. Papachristos
STL Containers
Unordered Map(s) ( std::unordered_map< …,… > )
Basic attributes – Unique Keys :
Basic functions:
STL
CS-202 C. Papachristos
STL Containers
A Cheatsheet for:
Double-ended Queue(s) – Deque(s) …
Priority Queue(s) …
Doubly-Linked List(s)
Forward-Linked List(s)
Many more …
STL
CS-202 C. Papachristos
STL Iterators
Iteration over STL Container elements.
(Remember: Like std::vector<T>::at(size_t pos); conveniently does.)
Iterators
STL
CS-202 C. Papachristos
STL Iterators
Access elements in any STL Container using a unified interface, regardless of the internal details of the Container itself.
Any such Iterator should be able to perform:
STL
CS-202 C. Papachristos
STL Iterators
Iterator Operations
intVec_it = intVec.begin();
intVec_it = intVec.end();
Handling of empty range condition: intVec.begin()==intVec.end().
++intVec_it; / intVec_it++;
--intVec_it; / intVec_it--;
a) A STL Vector Container of Type int
std::vector<int> intVec;
b) An Iterator for a STL Vector of Type int
std::vector<int>::iterator intVec_it;
Returns an iterator (pointing) to first element in Container.
Returns an iterator to one element past the last of the Container.
Advances iterator (element it is pointed to) by one, forward or backward.
Note:
Kinds of Iterators include Forward Its (++ works), Bidirectional Its (++/-- works), Random Access Its (++/-- works).
STL
CS-202 C. Papachristos
STL Iterators
Iterator Operations
if (!intVec.empty())
intVec_it = intVec.begin();
int intVec_element0 = * intVec_it ;
}
Dereferencing returns a Reference-to the Container’s element pointed-to by the Iterator.
a) A STL Vector Container of Type int
std::vector<int> intVec;
b) An Iterator for a STL Vector of Type int
std::vector<int>::iterator intVec_it;
Note:
Attention, the end() Iterator is pointed to one element past the last in the Container.
Set Iterator to point to first element in the Container.
Checking with empty() is usually faster than checking size()>0.
intVec_it = intVec.end();
* intVec_it;
Undefined Behavior
STL
CS-202 C. Papachristos
STL Iterators
Iterator Operations
Behavior of Dereferencing an Iterator dictates if it is Constant / Mutable.
Mutable Iterator
Example:
*it Returns an lvalue
*it can be on the left-(or right)-hand side of the assignment operator.
STL
CS-202 C. Papachristos
STL Iterators
Iterator Operations
Behavior of Dereferencing an Iterator dictates if it is Constant / Mutable.
Constant Iterator
Example:
*it = <anything>; Illegal
*it can only be on the right-hand side of the assignment operator.
STL
CS-202 C. Papachristos
STL Iterators
Iterator Operators
STL
CS-202 C. Papachristos
STL Iterators
Iterator Operations – std::vector<T>
Container Traversal w/ Iterator(s)
#include <vector>
std::vector<int> intVec;
intVec.push_back( 1 );
intVec.push_back( 5 );
…
for (std::vector<int>::iterator it = intVec.begin();
it != intVec.end();
++it)
{
std::cout << *it << std::endl;
}
Declare Iterator for STL Vector�of Type int.
STL
CS-202 C. Papachristos
STL Iterators
Iterator Operations – std::list<T>
Container Traversal w/ Iterator(s)
#include <list>
std::list<int> intList;
intList.push_back( 1 );
intList.push_front( 5 );
…
for (std::list<int>::iterator it = intList.begin();
it != intList.end();
++it)
{
std::cout << *it << std::endl;
}
Declare Iterator for STL List�of Type int.
STL
CS-202 C. Papachristos
STL Iterators
Reverse-Iterator(s)
Container Reverse-Traversal w/ Reverse-Iterator(s)
a) A STL Vector Container of Type int.
std::vector<int> intVec;
b) A Reverse-Iterator for a STL Vector of Type int.
std::vector<int>::reverse_iterator intVec_revit;
for ( intVec_revit = intVec.rbegin();
intVec_revit != intVec.rend();
++intVec_revit )
{
std::cout << *intVec_revit << std::endl;
}
STL
CS-202 C. Papachristos
STL Iterators
Iterator Examples – std::set<Key>
int main ( ) {
set<int> iSet;
iSet.insert(4);
iSet.insert(12);
iSet.insert(7);
/* the same looping construct for traversal */
for (set<int>::const_iterator it = iSet.begin(); it != iSet.end(); ++it)
{
cout << *it << endl;
}
return 0;
}
A Constant (non-Mutable) Iterator for a STL Set of Type int.
Output:
4
7
12
STL
CS-202 C. Papachristos
STL Iterators
Iterator Examples – std::map<Key,T>
int main ( ) {
map<string, float> stocks;
stocks.insert( make_pair( string("IBM"), 42.50) );
stocks.insert( make_pair( string("MS"), 2.50) );
stocks.insert( make_pair( string("FB"), 0.50) );
/* the same looping construct for traversal */
for (map<const string,float>::iterator it=stocks.begin(); it!=stocks.end(); ++it)
{
cout << it->first << "," << it->second << endl;
}
return 0;
}
Iterator for STL Map functions�like a Pointer to a Pair Struct.
Output:
FB,0.5
IBM,42.5
MS,2.5
Template(s)
CS-202 C. Papachristos
Remember: The template Parameter(s) List
The Template Parameter(s) List – More General.
template < typename T, typename U, typename V, int N, char C >
return-type func_tpl_name(parameters-list){ … }
template < typename T, typename U, typename V, int N, char C >
class ClassTplName { … };
template < typename T = int , size_t N = MAX_ELEMENTS >
class ClassTplDfltParamsName {
…
};
Note:
Used to be only for Class Templates, from C++11 supported fully.
Template(s)
CS-202 C. Papachristos
Advanced: The template Parameter(s) List
Template Template Param(s) : template< template< … > >
A simple Class Template:
template < typename T >
class TplClass{ public: TplClass(); … private: T * m_t_Pt; … };
A simple Type parameter T.
Note:
Not any more either,�but not a bad practice!
Template(s)
CS-202 C. Papachristos
Advanced: The template Parameter(s) List
Template Template Param(s) : template< template< … > >
A simple Class Template:
template < typename T >
class TplClass{ public: TplClass(); … private: T * m_t_Pt; … };
Another Class Template, for which one Template Type is another Class Template:
template < typename T , template < typename > class ClassTpl >
class ClassTplTpl {
public: …
private:
ClassTpl < T > m_classTpl;
…
};
2 Type Parameters: one is a simple T , and one is a Class Template ClassTpl<…> .
A member that is of a generalized Class Type that is itself templated for a some Type.
Template(s)
CS-202 C. Papachristos
Advanced: The template Parameter(s) List
Template Template Param(s) : template< template< … > >
A simple Class Template:
template < typename T >
class TplClass{ public: TplClass(); … private: T * m_t_Pt; … };
Another Class Template, for which one Template Type is another Class Template:
template < typename T , template < typename > class ClassTpl >
class ClassTplTpl {
public: …
private:
ClassTpl < T > m_classTpl;
…
};
Note1: Template Template syntax (used to) need keyword class to compile.
Note: There is no Template Template Template in C++.
Note2: We don’t even need to specify typename U here, all the compiler cares about is ClassTpl.
Template(s)
CS-202 C. Papachristos
Advanced: The template Parameter(s) List
Template Template Param(s) : template< template< … > >
2 (or more) different�Class Templates:
The Class Template�Class Template:
Possible to create:
AdvancedClass< int , ClassA > intAType;
AdvancedClass< Car , ClassB > carBType;
template < typename T >
class ClassA {
public: ClassA();
private: T m_t_arr[…];
};
template < typename T >
class ClassB {
public: ClassB();
private: T * m_t_Pt;
};
template <typename T, template < typename > class ClassTpl>
class AdvancedClass {
public: …
private:
ClassTpl < T > m_advanced; …
};
m_advanced is of ClassA for int Types !
m_advanced is of ClassB for Car Types !
Template(s)
CS-202 C. Papachristos
Advanced: The template Parameter(s) List
Template Template Param(s) : template< template< … > >
2 (or more) different�Templated Classes�for element storage:
A Class Template�Class Template�acting as an Adapter:
Create Queue variations:
Queue< int, CircularArray > int_qA;
Queue< Car, ForwardList > car_qL;
template < typename T >
class CircularArray {
public: CircularArray();
private: T m_arr[…]; ...
};
template < typename T >
class ForwardList {
public: ForwardList();
private: Node <T> * m_head; ...
};
template <class Type, template < typename > class ContainerType>
class Queue { //or class Stack, or another DDS container adapter
public: …
private:
ContainerType < Type > m_container; …
};
m_container is CircularArray w/ ints!
m_container is ForwardList w/ Cars !
Remember: Queue(s) as Container Adaptors
CS-202 C. Papachristos
#ifndef QUEUE_HPP_
#define QUEUE_HPP_
// default-used container class template header
#include <CircularArray/CircularArray.hpp>
template <typename Type,
template <typename> class ContainerType = CircularArray>
class Queue{
public:
Queue();
Queue(size_t count, const Type & val = Type());
Queue(const Queue<Type,ContainerType> & other);
~Queue();
Queue<Type,ContainerType> & operator=(
const Queue<Type,ContainerType> & other);
bool empty() const;
size_t size() const;
void push(const Type & value);
void pop();
void clear();
Type & front(); const Type & front() const;
Type & back(); const Type & back() const;
private:
ContainerType<Type> m_container;
};
//class template Queue method implementations ...
#endif
“Common” Header File: Queue.hpp
#ifndef FORWARD_LIST_HPP_
#define FORWARD_LIST_HPP_
template <typename Type>
class ForwardList {
// Node helper struct
template <typename>
struct Node { … Type m_data; Node<Type> * m_next; };
public:
ForwardList();
...
private:
Node<Type> * m_front, * m_back;
};
//class template ForwardList implementations ...
#endif
#ifndef CIRCULAR_ARRAY_HPP_
#define CIRCULAR_ARRAY_HPP_
template <typename Type>
class CircularArray {
public:
CircularArray();
...
private:
Type * m_data;
std::size_t m_size, m_front, m_back, m_capacity;
};
//class template CircularArray implementations ...
#endif
Time for Questions !
CS-202
CS-202 C. Papachristos