Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A templated class is larger than non-template class using same type?

Tags:

c++

templates

I was once asked a trick question at a job interview: does a templated class take more memory than another class which is identical but not templated? My answer was no, but the fact that he asked the question means there's probably a case where there is. Or, he really wanted to screw with me. What would be a case where a templated class would take more memory?

like image 252
djcouchycouch Avatar asked Mar 11 '13 16:03

djcouchycouch


People also ask

Can a non templated class have a templated member function?

A non-template class can have template member functions, if required. Notice the syntax. Unlike a member function for a template class, a template member function is just like a free template function but scoped to its containing class.

What is a templated class?

Definition. As per the standard definition, a template class in C++ is a class that allows the programmer to operate with generic data types. This allows the class to be used on many different data types as per the requirements without the need of being re-written for each type.

What is the difference between Typename and class in template?

There is no difference between using <typename T> OR <class T> ; i.e. it is a convention used by C++ programmers.

What is the difference between a class template and an ordinary class?

An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. Note the distinction between the terms class template and template class: Class template.


2 Answers

The first thing is making it clear what the meaning of the question is. If the question is whether the objects of the type are going to be larger (i.e. sizeof(T<int>) > sizeof(T_int)) then the answer is no. If the question is about the binary footprint of the application itself, including the code for the functions, then the answer is that the overall size of the program might actually be smaller in the case of a template as only used member functions will be compiled (unless explicitly instantiated). Although at the end of the day, the linker could potentially discard unused members from the non-template version also.

There is a common term: code bloat that is used to refer to the explosion of code generated by templates. The term refers to the fact that each different instantiation of a template will generate its own functions, and that can cause more functions to be present in the executable than having a smaller set of non-template functions for which conversions of the arguments are allowed.

Consider a possible interface for a vector template:

template <typename T>
class Vector {
   template <typename U> void push_back(U u);
//....

For every call to push_back with a different argument type, a new function will be generated, so there will be a function for Vector<int>::push_back('a') and another one for Vector<int>::push_back(1). Compare that with the interface of std::vector in which the member function is not a template and the caller does the type conversion.

While this can be a source of larger executables, I don't consider this to be what was asked for. In particular, for a templated type, and the equivalent non-template type handcrafted for the particular instantiated type, the generated code should be equivalent (ignoring the fact that mangled names tend to be larger for templates :))

like image 122
David Rodríguez - dribeas Avatar answered Oct 19 '22 03:10

David Rodríguez - dribeas


The answer is NO, as far as memory is concerned. I mean, it does not necessarily has to take more memory, though some evil guy might write a class template just to prove his point that class template version takes more memory.

However, the source code of the class template could be bigger (or lesser for that matter) than a non-template clas versions for a particular value(s) of the type parameter(s).

template<typename T>
struct point_t
{
    T x, y, z;
};

struct point_int
{
    int x, y, z;
};

std::cout << (sizeof(point_int) == sizeof(point_t<int>)) << std::end;

It will print true (or 1).

Note only that the memory layout of point_int and point_t<int> will be same. So you can even cast like this:

point_t<int>  pt {10, 20, 30};

point_int  pi = *reinterpret_cast<point_int*>(&pt);

std::cout << "{" << pi.x <<"," << pi.y <<"," << pi.z << "}" << std::endl;

It will print {10, 20, 30}.

  • Online Demo

Hope that helps.

like image 33
Nawaz Avatar answered Oct 19 '22 03:10

Nawaz