10 KiB
[temp.dep.res]
13 Templates [temp]
13.8 Name resolution [temp.res]
13.8.4 Dependent name resolution [temp.dep.res]
13.8.4.1 Point of instantiation [temp.point]
For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization.
Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.
If a function template or member function of a class template is called in a way which uses the definition of a default argument of that function template or member function, the point of instantiation of the default argument is the point of instantiation of the function template or member function specialization.
For a noexcept-specifier of a function template specialization or specialization of a member function of a class template, if the noexcept-specifier is implicitly instantiated because it is needed by another template specialization and the context that requires it depends on a template parameter, the point of instantiation of thenoexcept-specifier is the point of instantiation of the specialization that requires it.
Otherwise, the point of instantiation for such a noexcept-specifier immediately follows the namespace scope declaration or definition that requires thenoexcept-specifier.
For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template.
Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.
If a virtual function is implicitly instantiated, its point of instantiation is immediately following the point of instantiation of its enclosing class template specialization.
An explicit instantiation definition is an instantiation point for the specialization or specializations specified by the explicit instantiation.
A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above,
for any such specialization that has a point of instantiation within thedeclaration-seq of thetranslation-unit, prior to the private-module-fragment (if any), the point after the declaration-seq of the translation-unit is also considered a point of instantiation, and
for any such specialization that has a point of instantiation within the private-module-fragment, the end of the translation unit is also considered a point of instantiation.
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, the program is ill-formed, no diagnostic required.
For the compound-statement of an expansion statement ([stmt.expand]), the point of instantiation is the point of instantiation of its enclosing templated entity, if any.
Otherwise, it immediately follows the namespace-scope declaration or definition that contains the expansion statement.
13.8.4.2 Candidate functions [temp.dep.candidate]
If a dependent call ([temp.dep]) would be ill-formed or would find a better match had the lookup for its dependent name considered all the function declarations with external linkage introduced in the associated namespaces in all translation units, not just considering those declarations found in the template definition and template instantiation contexts ([basic.lookup.argdep]), then the program is ill-formed, no diagnostic required.
[Example 1:
Source file "X.h":namespace Q {struct X { };}
Source file "G.h":namespace Q {void g_impl(X, X);}
Module interface unit of M1:module;#include "X.h"#include "G.h"export module M1;export templatevoid g(T t) { g_impl(t, Q::X{ }); // ADL in definition context finds Q::g_impl, g_impl not discarded}
Module interface unit of M2:module;#include "X.h"export module M2;import M1;void h(Q::X x) { g(x); // OK} â end example]
[Example 2:
Module interface unit of Std:export module Std;export templatevoid indirect_swap(Iter lhs, Iter rhs){ swap(*lhs, *rhs); // swap not found by unqualified lookup, can be found only via ADL}
Module interface unit of M:export module M;import Std;
struct S { /* .../ };void swap(S&, S&); // #1void f(S p, S* q){ indirect_swap(p, q); // finds #1 via ADL in instantiation context} â end example]
[Example 3:
Source file "X.h":struct X { /* ... */ }; X operator+(X, X);
Module interface unit of F:export module F;export templatevoid f(T t) { t + t;}
Module interface unit of M:module;#include "X.h"export module M;import F;void g(X x) { f(x); // OK, instantiates f from F,// operator+ is visible in instantiation context} â end example]
[Example 4:
Module interface unit of A:export module A;export templatevoid f(T t) { cat(t, t); // #1 dog(t, t); // #2}
Module interface unit of B:export module B;import A;export template<typename T, typename U>void g(T t, U u) { f(t);}
Source file "foo.h", not an importable header:struct foo {friend int cat(foo, foo);};int dog(foo, foo);
Module interface unit of C1:module;#include "foo.h" // dog not referenced, discardedexport module C1;import B;export templatevoid h(T t) { g(foo{ }, t);}
Translation unit:import C1;void i() { h(0); // error: dog not found at #2}
Importable header "bar.h":struct bar {friend int cat(bar, bar);};int dog(bar, bar);
Module interface unit of C2:module;#include "bar.h" // imports header unit "bar.h"export module C2;import B;export templatevoid j(T t) { g(bar{ }, t);}
Translation unit:import C2;void k() { j(0); // OK, dog found in instantiation context:// visible at end of module interface unit of C2} â end example]