2

When you write a template function (or member) you have to write the body in the header file. This makes perfect sense since templates are essentially instructions to the compiler how to make functions on the fly based on a type unknown until the initialization.

My question is connected to the one definition rule, if I initialize a template with the same type (for example typename T becomes int) in two different files and I link them together I do not have a multiple definition error.

What is the reason? Are template functions implicitly static and so not visible outside their compilation unit?

Or there is another reason?

Answer: No. They aren't. They are an exception to the one definition rule.

2
  • A better model would be to consider them to be implicitly inline. Commented Mar 7, 2015 at 15:44
  • A function template is not a function, so there's a separate part of the one-definition-rule that applies to function templates. Those rules imply that all instantiations of the same function template specialization are the same, and they must indeed be deduplicated by the translator. (E.g. all functions f<int> share the same block-local static variables.) Commented Mar 7, 2015 at 16:00

1 Answer 1

3

The standard contains a special exception in the one definition rule for templates.

N4140, emphasis mine:

3.2 One definition rule [basic.def.odr]

6 There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. [...]

Those following requirements effectively state that all definitions are required to be identical, but I'm assuming they are in your code.

You can tell that template functions are neither implicitly inline nor implicitly static by the fact that this program works:

a.cc:

template <typename T> T f();
int main() { return f<int>(); }

b.cc:

template <typename T> T f() { return T(); }
template int f();

If templates were implicitly inline, this program would be invalid because an inline function must be defined in every translation unit where it is used.

If templates were implicitly static, this program would be invalid because the definition in b.cc would not be found to match the declaration in a.cc.

Sign up to request clarification or add additional context in comments.

10 Comments

Very interesting example, time ago I tried the same with an inline function: inline int f() { return 1; } in one file and int f(); int main() { return f(); } in another to see if inline function are implicitly static (they are). Instead templates work differently.
@Paolo.Bolzoni Those are not implicitly static either. They do require a definition in each translation unit where they are used. However, those definitions get merged: if you obtain the address of f in one translation unit, and compare that to the address of f obtained from another translation unit, you'll find they're the same.
Shouldn't that last line of code be template<> int f<int>(); ?
@BenVoigt No, it's supposed to be an explicit instantiation, not a specialisation.
Ok, then template int f<int>();
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.