Skip to content

Case 229: Exported Template Default Changed

Field Value
Verdict 🔴 BREAKING
Category Breaking
Classification Rule
Platforms Linux, macOS, Windows
Flags ABI break
Detected ChangeKinds default_template_arg_changed
Source files catalog/cases/case229_exported_template_default_changed/
Rule family exported-template-default-changed
Subject Template and generic-programming issues

Category: Template ABI | Verdict: 🔴 BREAKING

Verdict and consumer impact

The library exports the instantiation Box<int>, which carries the default U = T. The default becomes U = long, so the default-substituted instantiation Box<int, int> disappears and Box<int, long> appears. This is the shape-A case (the exported-instantiation shape). A consumer built against v1 cannot find the old symbol. The verdict is BREAKING, with default_template_arg_changed as the explanation.

This case checks that the header-level kind does not also fire. The exported instantiation already covers the template, so the header-level relation is recorded as DEDUPLICATED, and template_param_default_changed is absent from the output.

Old/new diff

v1.h v2.h
template <typename T, typename U = T> class Box; template <typename T, typename U = long> class Box;

abicheck command

g++ -shared -fPIC -g -std=c++17 -I. v1.cpp -o libfoo_v1.so
g++ -shared -fPIC -g -std=c++17 -I. v2.cpp -o libfoo_v2.so
abicheck compare libfoo_v1.so libfoo_v2.so -H old=v1.h -H new=v2.h

Expected abicheck finding

Verdict: BREAKING
- default_template_arg_changed: Box<int, int> -> Box<int, long>
- func_removed / instantiation_missing_from_binary: Box<int, int> symbols

Minimum evidence

min_evidence: L2, so the exported symbols and the public header are both present.

Why abicheck catches it

detect_default_template_arg_changed finds the exported instantiation. Its callable stem covers the header-level relation, so the relation is suppressed and recorded as DEDUPLICATED (policy/template_default_changes.py).

Runtime failure demonstration

Build the old library and a consumer against v1, then swap in v2. The consumer fails to resolve the Box<int, int> symbol.

Safe redesign

Never change the default of a template whose instantiations ship. Add an explicitly named alias instead, as in case87.


Source files

  • CMakeLists.txt
  • app.cpp
  • v1.cpp
  • v1.h
  • v2.cpp
  • v2.h

See also: Compatibility Catalog · All BREAKING cases · Category: Breaking · Rule: Exported template default changed · Subject: Template and generic-programming issues.