Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is a C++ template instantiation type checked?

Tags:

c++

templates

When compiling C++, gcc and clang seems to postpone the type-checking of template instantiations until after all declarations of the program have been processed. Is this guaranteed in the language?

To elaborate, I can keep a type incomplete at the point where a template is defined or a template instantiation is needed, as long as I complete the type somewhere later in the program:

class A;
class B;

extern A* pa;

// 1. template definition
template<typename T>
T* f() { return static_cast<T*>(pa); }

// 2. template instantiation
B* test() { return f<B>(); }

// 3. completing types
class A { };
class B : public A { };

Note that the definitions of A and B are required to type check the template instantiation (to make the static_cast valid). If you leave out step 3, step 2 will no longer compile.

In the organisation of my headers, can I rely that this order will be accepted by any standard C++ compiler?

like image 769
Bruno De Fraine Avatar asked Dec 10 '15 14:12

Bruno De Fraine


People also ask

How the instantiation of function template happens?

When a function template is first called for each type, the compiler creates an instantiation. Each instantiation is a version of the templated function specialized for the type. This instantiation will be called every time the function is used for the type.

Why we need to instantiate the template?

Class template instantiationIn order for any code to appear, a template must be instantiated: the template arguments must be provided so that the compiler can generate an actual class (or function, from a function template).

Are templates instantiated at compile time?

1.1.2 Using Function Templates A template is visited twice by the compiler. On first pass it's simply checked for correct syntax. It's only actually compiled when it is used (instantiated) in code.

What is the instantiation of the class template?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation.


1 Answers

The rule is called "two-phase name lookup".

The names, which are not dependant on the template parameters, are looked up and checked at definition, and the dependent names are checked at the point of instantiation.

For your example, there is one important detail: the end of translation unit is also considered a point of instantiation for function templates:

C++14 N4140 14.6.4.1 [temp.point] P8:

A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation.

Thus, although the type is incomplete at point "2", where explicit instantiation happens, it is complete at the end of file, which makes the template instantiation legitimate.

Note: Microsoft compiler does not implement this rule in full, violating the standard. In Microsoft compiler, all the lookup happens at the point of instantiation (thus the example should also work, but I don't have access to MSVC to check). Other major compilers do implement this rule correctly.

like image 112
Ilya Popov Avatar answered Oct 22 '22 13:10

Ilya Popov