C++11coreintermediate
extern template (C++11 Addition)
C++11 · Modern Revolution · Compiler flag: -std=c++11
Explanation
Prevents implicit instantiation of a template in a translation unit, reducing compilation time by declaring that the instantiation exists elsewhere.
Real-World Scenario
Speed up build times in a large project by instantiating `std::vector<std::string>` in one source file and using `extern template` in all headers.
Quick Snippet
snippet.cpp
// header.h
extern template class std::vector<std::string>; // suppress instantiation here
// source.cpp
template class std::vector<std::string>; // explicit instantiation hereFull Example
extern_template.cpp
// CodeNebula - C++11 Example: Extern Template
// Compile: g++ -std=c++11 -Wall -Wextra -o example extern_template.cpp
//
// This example demonstrates:
// - extern template to suppress implicit instantiation
// - How it reduces compile time by avoiding duplicate instantiations
// - Explicit instantiation definition vs extern template declaration
// - Practical usage pattern across translation units
#include <iostream>
#include <string>
#include <vector>
// ============================================================
// 1. A template class that would normally be instantiated
// in every translation unit that uses it
// ============================================================
template <typename T>
class Accumulator {
T total_;
int count_;
public:
Accumulator() : total_(T()), count_(0) {}
void add(const T& value) {
total_ += value;
++count_;
}
T getTotal() const { return total_; }
int getCount() const { return count_; }
double getAverage() const {
return (count_ > 0) ? static_cast<double>(total_) / count_ : 0.0;
}
void print(const std::string& label) const {
std::cout << label << ": total=" << total_
<< ", count=" << count_
<< ", avg=" << getAverage() << std::endl;
}
};
// ============================================================
// 2. Extern template declaration
// ============================================================
// In a real multi-file project, this would go in a header:
// extern template class Accumulator<int>;
// extern template class Accumulator<double>;
//
// And one .cpp file would contain the explicit instantiation:
// template class Accumulator<int>;
// template class Accumulator<double>;
//
// This prevents the compiler from instantiating these
// specializations in every translation unit that includes
// the header, reducing compile time and object file size.
// For this single-file demo, we use explicit instantiation:
template class Accumulator<int>;
template class Accumulator<double>;
// ============================================================
// 3. Template function with extern template
// ============================================================
template <typename T>
T clamp(T value, T low, T high) {
if (value < low) return low;
if (value > high) return high;
return value;
}
// Explicit instantiation for common types
template int clamp<int>(int, int, int);
template double clamp<double>(double, double, double);
// In other translation units, you would write:
// extern template int clamp<int>(int, int, int);
// extern template double clamp<double>(double, double, double);
// ============================================================
// 4. std::vector extern template (common real-world usage)
// ============================================================
// Many standard library implementations use this internally:
// extern template class std::vector<int>;
// to speed up compilation of commonly-used instantiations.
int main() {
std::cout << "=== Extern Template ===" << std::endl;
// Using explicitly instantiated class template
Accumulator<int> intAcc;
intAcc.add(10);
intAcc.add(20);
intAcc.add(30);
intAcc.print("int accumulator");
Accumulator<double> dblAcc;
dblAcc.add(1.5);
dblAcc.add(2.5);
dblAcc.add(3.5);
dblAcc.print("double accumulator");
// Using explicitly instantiated function template
std::cout << "clamp(15, 0, 10) = " << clamp(15, 0, 10) << std::endl;
std::cout << "clamp(-5, 0, 10) = " << clamp(-5, 0, 10) << std::endl;
std::cout << "clamp(5, 0, 10) = " << clamp(5, 0, 10) << std::endl;
std::cout << "clamp(3.7, 1.0, 3.0) = " << clamp(3.7, 1.0, 3.0) << std::endl;
// Summary of the pattern
std::cout << "\n--- Extern Template Pattern ---" << std::endl;
std::cout << "Header: extern template class Foo<int>;" << std::endl;
std::cout << "One .cpp: template class Foo<int>;" << std::endl;
std::cout << "Result: Faster compilation, smaller object files" << std::endl;
return 0;
}
// Expected output:
// === Extern Template ===
// int accumulator: total=60, count=3, avg=20
// double accumulator: total=7.5, count=3, avg=2.5
// clamp(15, 0, 10) = 10
// clamp(-5, 0, 10) = 0
// clamp(5, 0, 10) = 5
// clamp(3.7, 1.0, 3.0) = 3
//
// --- Extern Template Pattern ---
// Header: extern template class Foo<int>;
// One .cpp: template class Foo<int>;
// Result: Faster compilation, smaller object files
Run command
g++ -std=c++11 -Wall -Wextra -o example extern_template.cpp