CppCon B2B Talk C++ Templates - Questions and Answers
This post tries to answer some of the questions posted during my two talks at CppCon 2020:
Here are the videos for both parts:
Well, no. The exception being, if you tell the compiler by explicitly stating the arguments of a function-template. Suppose we have a function template and the two variables x
and y
like this:
1 2 3 4 5 6 7 8 |
|
When we call equal
with the two variables equal(x, y)
, the compiler refuses to compile it. It tells us that both parameters of equal
must be of the same type. No implicit conversion happens. For a case like this, it could be desirable to make it work. You can do that by explicitly calling the template for a type equal<int>(x, y)
. This turns implicit conversions on, as we practically ask the compiler to make up an instantiation for int
and then call that function. If there is no type deduction going on, which we disabled in this case, we have implicit conversions.
To set the context here, we are talking about this example form my talk (I modified it here to be shorter):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
As you can see, Array
is a struct
and mData
is a public member. With that, Array
works like an aggregate. This is the version libc++ uses as it creates no overhead. You can even create an uninitialized version.
We cannot define classes multiple times. However, each template parameter combination for a class creates a new type. For example:
1 2 3 4 5 |
|
In the code above A<int>
is a type and A<double>
is another type. They start with or use the same class as template, but the stamped out versions are different types. Think of it as filling out a registration form for a conference. We all fill in the blanks with different values. My name is probably different from yours. I hope that at least my bank account number differs. So the result is that the organizer gets a lot of different results (instantiations) for the same form (template). We are all attending the same event, yet we are all different people.
If you create arrays with the same type but different size (e.g. Array<int,2>
and Array<int,3>
), does it generate code for the class of each of those separably? Does this have implications on size/speed? _Yes, it does. See the question above, Array<int,2>
and Array<int,3>
are two different types. The first has an internal array of size 2
while the second has one of size 3
. What the size
method returns is also different. That means that you end up with code for both. However, remember that you explicitly requested them. Without templates, you would probably have created Array2
and Array3
by hand and via copy & paste.
You can use C++ Insights to get a better view of the insides. Here is an example cppinsights.io/s/bb1fbd72. In the transformation, you can see that you get practically two distinct types:_
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Well, templates more or less require to be declared and implemented in a header file. The compiler needs to see and know the code we have written for a certain function template or class template method. Otherwise, it is not able to instantiate it. This makes header-only libraries, especially when it comes to templates, the defacto default. Since C++17, we can also have inline
static
member variables. They can be initialized inline. This drops another reason for having a source file along with the header. We no longer need that source file for the initialization code of our class template.
Must Bar
also be a class template, or is the following also okay?
1 |
|
Bar
doesn't need to be a class template. In the original example (as shown below), I made Bar
a class template as well. This was to show that to call a method from Foo
in Bar
comes with some exceptions if Bar
is a class template as well.
1 2 |
|
If a non-template (or template) class inherits from a template class, can you use dynamic_cast to convert to/from the parent/child class?
Yes, you can, but you have to provide the full type. That means the class template with its template parameters. Suppose you have a class template A
:
1 2 |
|
When you like to use dynamic_cast
with A
, then you have to say, for example: dynamic_cast< A<int> >(yourInstance)
.
No. CRTP refers to a special kind of inheritance where the base class template takes the derived class as template argument. You find a definition with an example at wikipedia.org
Can inheritance and templates be combined to call say member function foo
from base to derived by explicitly calling derived Foo
using class template type rather than dynamic pointer? Inheriting from a class template is no different than inheriting from a regular class. The compiler still needs to adjust the this
-pointer when calling a method in the base class.
They work together. A module can export the definition of a template.
- C++ Templates: The Complete Guide (second edition covering up to C++17)
- C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond (a bit older)
- Notebook C++: Tips and Tricks with Templates (my own book)
I hope this answers your questions. Should I have misunderstood a question, or you need further clarification, feel free to reach out to me via email or X.
Andreas