Annex G (informative) Ill-formed, no diagnostic required [ifndr]

G.10 [temp]: Templates [ifndr.temp]

G.10.1[ifndr:temp.pre.reach.def]
Specified in: [temp.pre]

A definition of a function template, member function of a class template, variable template, or static data member of a class template that is not reachable from the end of every definition domain ([basic.def.odr]) in which it is implicitly instantiated ([temp.inst]) and whose corresponding specialization is not explicitly instantiated ([temp.explicit]) in some translation unit is ill-formed, no diagnostic required.
[Example 1: 

Source file "a.h":template <typename T> void f();

Source file "a.cpp":#include "a.h" int main() { f<int>(); // IFNDR, function template implicitly instantiated but not reachable definition } — end example]

G.10.2[ifndr:temp.arg.template.sat.constraints]
Specified in: [temp.arg.template]

Any partial specializations ([temp.spec.partial]) associated with the primary template are considered when a specialization based on the template template-parameter is instantiated.
If a specialization is not reachable from the point of instantiation, and it would have been selected had it been reachable, the program is ill-formed, no diagnostic required.
[Example 1: template<class T> struct A { int x; }; template<template<class U> class V> struct C { V<int> y; V<int*> z; }; C<A> c; // IFNDR, specialization is not reachable from point of instantiation above and it would have // been selected if it had template<class T> struct A<T*> { long x; }; — end example]

G.10.3[ifndr:temp.constr.atomic.equiv.but.not.equiv]
Specified in: [temp.constr.atomic]

If the validity or meaning of the program depends on whether two atomic constraints are equivalent, and they are functionally equivalent but not equivalent, the program is ill-formed, no diagnostic required.
[Example 1: template <int N> concept Add1 = true; template <unsigned N> void f2() requires Add1<2 * N>; template <unsigned N> int f2() requires Add1<N * 2> && true; void h2() { f2<0>(); // IFNDR, requires determination of subsumption between atomic constraints // that are functionally equivalent but not equivalent } — end example]

G.10.4[ifndr:temp.constr.atomic.sat.result.diff]
Specified in: [temp.constr.atomic]

If, at different points in the program, the satisfaction result is different for identical atomic constraints and template arguments, the program is ill-formed, no diagnostic required.
[Example 1: template<class T> concept Complete = sizeof(T) == sizeof(T); struct A; static_assert(!Complete<A>); // #1 struct A {}; static_assert(Complete<A>); // IFNDR, satisfaction result differs from point #1 — end example]

G.10.5[ifndr:temp.constr.normal.invalid]
Specified in: [temp.constr.normal]

If during constraint normalization any such substitution results in an invalid type or expression, the program is ill-formed, no diagnostic is required.
[Example 1: template<typename T> concept A = T::value || true; template<typename U> concept B = A<U*>; template<typename V> concept C = B<V&>; // IFNDR, it would form the invalid type V&* // in the parameter mapping — end example]

G.10.6[ifndr:temp.spec.partial.general.partial.reachable]

If a partial specialization is not reachable from a use of a template specialization that would make use of that partial specialization as the result of an implicit or explicit instantiation, the program is ill-formed, no diagnostic required.
[Example 1: template<typename T> class X{ public: void foo(){}; }; template class X<void *>; // IFNDR, explicit instantiation and partial specialization is not reachable template<typename T> class X<T*>{ public: void baz(); }; — end example]

G.10.7[ifndr:temp.over.link.equiv.not.equiv]
Specified in: [temp.over.link]

If the validity or meaning of the program depends on whether two constructs are equivalent, and they are functionally equivalent but not equivalent, the program is ill-formed, no diagnostic required.
[Example 1: template <int I> struct A{}; // IFNDR, the following declarations are functionally equivalent but not equivalent template <int I> void f(A<I>, A<I+10>); template <int I> void f(A<I>, A<I+1+2+3+4>); — end example]

G.10.8[ifndr:temp.res.general.default.but.not.found]
Specified in: [temp.res.general]

If the validity or meaning of the program would be changed by considering a default argument or default template argument introduced in a declaration that is reachable from the point of instantiation of a specialization ([temp.point]) but is not found by lookup for the specialization, the program is ill-formed, no diagnostic required.
[Example 1: void f(long); // #1 void f(int, int); // #2 template<typename T> void g(T t) { f(t); } void f(int, int = 0); // #3 void h() { g(0); } // IFNDR, selects #3 here but selects #1 using lookup for g<int> — end example]

G.10.9[ifndr:temp.point.diff.pt.diff.meaning]
Specified in: [temp.point]

A specialization for a class template has at most one point of instantiation within a translation unit.
A specialization for any template may have points of instantiation in multiple translation units.
If two different points of instantiation give a template specialization different meanings according to the one-definition rule ([basic.def.odr]), the program is ill-formed, no diagnostic required.
[Example 1: 

Source file "a.h":#include <type_traits> template <typename T, typename Enabler = void> struct is_complete : std::false_type {}; template <typename T> struct is_complete<T, std::void_t<decltype(sizeof(T) != 0)>> : std::true_type {};

Source file "a.cpp":#include "a.h" struct X; static_assert(!is_complete<X>::value); // IFNDR, different specialization selected in "b.cpp"

Source file "b.cpp":#include "a.h" struct X { }; static_assert(is_complete<X>::value); // IFNDR, different specialization selected in "a.cpp" — end example]

G.10.10[ifndr:temp.dep.candidate.different.lookup.different]
Specified in: [temp.dep.candidate]

If considering all function declarations with external linkage in the associated namespaces in all translations would make a dependent call ([temp.dep]) ill-formed or find a better match, the program is ill-formed, no diagnostic required.
[Example 1: 

Translation unit #1:namespace A { struct S {}; void f(S&, long x, int y); // #3 void g(S&, int x); // #4 }

Translation unit #2:namespace A { struct S {}; void f(S&, int x, long y); // #5 void g(S&, long x); // #6 } template <typename T> void h(T& t) { f(t, 1, 1); // Selects #5 in h<A​::​S>, would be ambiguous call if all declarations were considered. g(t, 1); // Selects #6 in h<A​::​S>, would select #4 if all declarations were considered. } — end example]

G.10.11[ifndr:temp.explicit.decl.implicit.inst]
Specified in: [temp.explicit]

If an entity that is the subject of an explicit instantiation declaration and that is also used in a way that would otherwise cause an implicit instantiation ([temp.inst]) in the translation unit is not the subject of an explicit instantiation definition somewhere in the program the program is ill-formed, no diagnostic required.
[Example 1: extern template class std::vector<int>; // explicit instantiation declaration int main() { std::cout << std::vector<int>().size(); // IFNDR, implicit instantiation but no explicit // instantiation definition } — end example]

G.10.12[ifndr:temp.expl.spec.unreachable.declaration]
Specified in: [temp.expl.spec]

If an implicit instantiation of a template would occur and there is an unreachable explicit specialization that would have matched, the program is ill-formed, no diagnostic required.
[Example 1: 

Source file "a.h":template <typename T> struct S {};

Translation unit #2:#include "a.h" template <> struct S<int> { int oops; }; // #1

Translation unit #3:#include "a.h" S<int> s; // IFNDR, #1 is not reachable but would have matched — end example]

G.10.13[ifndr:temp.expl.spec.missing.definition]
Specified in: [temp.expl.spec]

If an explicit specialization of a template is declared but there is no definition provided for that specialization, the program is ill-formed, no diagnostic required.
[Example 1: template <typename T> int f(T&&) { return 0; } template <> int f<int>(int&&); int j = f(1); // IFNDR, odr-use of f<int> with no definition — end example]

G.10.14[ifndr:temp.deduct.general.diff.order]
Specified in: [temp.deduct.general]

If substitution into different declarations of the same function template would cause template instantiations to occur in a different order or not at all, the program is ill-formed, no diagnostic required.
[Example 1: template <class T> struct A { using X = typename T::X; }; template <class T> typename T::X h(typename A<T>::X); // #1 template <class T> auto h(typename A<T>::X) -> typename T::X; // redeclaration #2 template <class T> void h(...) { } void x() { h<int>(0); // Substituting into #1 forms an invalid type from T​::​X and does // not attempt to instantiate A. // Substituting into #2 instantiates A<T>, which is ill-formed. } — end example]