// my_template.h
#include <iostream>
// Template function defined in the header file
template <typename T>
void printValue(const T& value) {
std::cout << "Value: " << value << std::endl;
}
#include "my_template.h"
void foo() {
printValue(42);
printValue(3.632);
printValue("=====");
}
// main.cpp
#include "my_template.h"
void foo();
int main() {
printValue(42);
printValue(3.14);
printValue("Hello, World!");
foo();
return 0;
}

Drawbacks:
An explicit instantiation declaration for a given function template instantiation must appear only once in a program.
// my_template.h
#include <iostream>
// Generic template declaration
template <typename T>
void printValue(const T& value);
// Explicit specialize template declaration
template <>
void printValue(const char& value);
// my_template.cpp
#include "my_template.h"
// Generic template function definition
template <typename T>
void printValue(const T& value) {
std::cout << "Value: " << value << std::endl;
}
// Specialized template function definition
template <>
void printValue(const char& value) {
std::cout << "Value: " << value << std::endl;
}
// The explicit instantiation must be preceded by the template definition
template void printValue<int>(const int&);
template void printValue<double>(const double&);
// main.cpp
#include "my_template.h"
int main() {
printValue('a');
printValue(42);
printValue(3.14);
return 0;
}
In g++, use the flag -fno-implicit-templates to supress the implicit instantiation.
Upside:
Downside:

An extern keyword which makes the compiler not compile a template function. You should use this if and only if you know it is used in the same binary somewhere else.
// main.cpp
#include "my_template.h"
// Ask compiler not to instantiate for types double, int, and char
// since compiler has done (or will do) in my_template.cpp
extern template void printValue<double>(const double&);
extern template void printValue<int>(const int&);
extern template void printValue<char>(const char&);
void another();
int main() {
another();
printValue('b'); // compiler instantiate
printValue(4);
printValue(3.14);
return 0;
}
// my_template.h
#include <iostream>
// Generic template function definition
template <typename T>
void printValue(const T& value) {
std::cout << "Value: " << value << std::endl;
}
// my_template.cpp
#include "my_template.h"
// Specialized template function definition
template <>
void printValue(const char& value) {
std::cout << "Value: " << value << std::endl;
}
void another(){
printValue('a');
printValue(1);
printValue(1.2);
}

T: Symbol is defined in this object file (.text section – code). W: Weak symbol — definition that can be overridden by a strong one. U: Undefined symbol — used but not defined in this object file. t: Local (non-global) symbol in .text.
Explicit instantiations vs. extern instantiations using extern template (C++11) to avoid instantiation
| Model | Extensible | Object file size | inlineable | Compilation speed |
|---|---|---|---|---|
| Inclusion | Yes | Largest | Yes | slowest |
| Explicit instantiation | No | Smallest | No | Fastest |
| Extern template | Small | Yes* | Fast | |
| C++20 Modules |