In the book "C++ Templats Complete Guide 2nd Edition" section "19.3 Type Functions", it asks the following question:
Assume that we have a number of container templates, such as std::vector<> and std::list<>, as well as built-in arrays. We want a type function that, given such a container type, produces the element type. This can be achieved using partial specialization.
then provides the following answer:
#include <vector>
#include <list>
#include <iostream>
#include <typeinfo>
template<typename T>
struct ElementT;
template<typename T>
struct ElementT<std::vector<T>>
{
using Type = T;
};
template<typename T>
struct ElementT<std::list<T>>
{
using Type = T;
};
template<typename T, std::size_t N>
struct ElementT<T[N]>
{
using Type = T;
};
template<typename T>
struct ElementT<T[]>
{
using Type = T;
};
template<typename T>
void printElementType(T const& c)
{
std::cout << "Container of "
<< typeid(typename ElementT<T>::Type).name()
<< " elements\n";
}
int main()
{
std::vector<int> intVec = {1, 2, 3};
std::list<double> doubleList = {1.1, 2.2, 3.3};
bool boolArr[] = {false, false, true, false, true};
//GNU COMPILER:
printElementType(intVec); //Container of i elements
printElementType(doubleList); //Container of d elements
printElementType(boolArr); //Container of b elements
}
My question is what is the advantage of such approach when we can write a simple function like bellow?
#include <iostream>
#include <typeinfo>
#include <vector>
#include <list>
template<typename T>
void printType(const T& container)
{
std::cout << "Container of "
<< typeid(T).name()
<< " elements\n";
}
int main()
{
std::vector<int> intVec = {1, 2, 3};
std::list<double> doubleList = {1.1, 2.2, 3.3};
bool boolArr[] = {false, false, true, false, true};
//GNU COMPILER:
printType(intVec); //Container of St6vectorIiSaIiEE elements
printType(doubleList); //Container of St4listIdSaIdEE elements
printType(boolArr); //Container of A5_b elements
}
Also second question: Why do results differ? What is this extra information?
Thank you very much.
2 major differences:
The book version gets the type of the elements in the container, while your versions simply prints the type of the container. Plus your version accepts any type, even if it's not a container. E.g. in the book's version the type is int
while in yours it's std::vector<int>
.
The book version "gets" the type. This can be further used to define other types. Your version prints the information. You can't do anything else than print it. You can't use it to compose other types or declare variables.
It's like the difference between:
int max(int a, int b)
{
if (a > b)
return a ;
else
return b;
}
and
void print_max(int a, int b)
{
if (a > b)
std::cout << a << '\n';
else
std::cout << b << '\n';
}
The first function is vastly superior to the second. You can use it to do other things that just print the maximum value. E.g.:
int max(int a, int b, int c) { return max(a, max(b, c)); }
Example of what you can do with the book version, but you can't with yours:
template <class Container>
typename ElementT<Container>::Type foo(const Container& cont)
{
typename ElementT<Container>::Type sum = 0;
for (const auto& e : cont)
{
sum += e;
}
return sum;
}