Search code examples
c++templateslinkage

Linkage of non-member template function


My own experiments show the instantiation of a non-member template function has internal linkage, however the answer to this other post seem to suggest that it has external.

It properly states it somewhere in the standard, but I have a hard time finding it.

My experiment

2 sources files and 1 header:

// source.hpp

#pragma once

#include <iostream>

template<typename T>
void print_size() {
    std::cout << "Size: " << sizeof(T) << std::endl;
}

void call_print_size();
// source.cpp

#include "source.hpp"

void call_print_size() {
    return print_size<int>();
}
// main.cpp

#include "source.hpp"

int main() {
    print_size<int>();
    call_print_size();
}

I'm compiling using MSVC from VS2022 Developer Command Prompt:

cl main.cpp source.cpp /std:c++17 /EHsc

If I'm correct, this would create 2 definitions of the int-instantiation of print_size; one in source.cpp and one in main.cpp. I would expect this to break the One-Definition Rule, if they have external linkage - however, it works just fine.


Solution

  • A function template declared without the keyword static at namespace scope(and some other conditions see below) have external linkage.

    From Linkage documentation:

    Any of the following names declared at namespace scope have external linkage, unless they are declared in an unnamed namespace or their declarations are attached to a named module and are not exported(since C++20):

    • names of all templates not listed above (that is, not function templates declared static).

    Additionally, from one definition rule:

    There can be more than one definition in a program of each of the following: class type, enumeration type, inline function, inline variable(since C++17), templated entity (template or member of template, but not full template specialization), as long as all of the following is true:

    • each definition consists of the same sequence of tokens (typically, appears in the same header file)

    If all these requirements are satisfied, the program behaves as if there is only one definition in the entire program. Otherwise, the program is ill-formed, no diagnostic required.

    Basically the linker can discard other definitions and just use any one of them(assuming they are exactly the same).