In the C++20 draft (N4868) there are two relevant rules about definition reachability:
[basic.def.odr/11] A definition of an inline function or variable shall be reachable from the end of every definition domain in which it is odr-used outside of a discarded statement.
[temp.pre/10] A definition of a function template … shall be reachable from the end of every definition domain in which it is implicitly instantiated … unless the corresponding specialization is explicitly instantiated … in some translation unit; no diagnostic is required.
Now consider the following program split into two files:
// file1.cpp
template<class T>
inline void foo(T a); // declaration
int main() {
foo(123); // implicit instantiation of foo<int>
}
// file2.cpp
#include <iostream>
template<class T>
inline void foo(T a) {
std::cout << a;
}
template void foo<int>(int); // explicit instantiation definition
This program compiles and runs under MSVC, printing 123.
By [temp.pre/10], this seems OK:
foo<int> is implicitly instantiated in file1.cpp, but there is an explicit instantiation in file2.cpp, so the definition doesn’t need to be reachable in file1.cpp.
But [basic.def.odr/11] says that an inline function definition must be reachable in every TU where it is ODR-used.
In file1.cpp, foo<int> is called (ODR-used), but there is no reachable definition of the inline function template there.
Is this program UB or not? More specifically:
A function template is not a function. It can be instantiated into a specialisation, and that specialisation is a function. (e.g., foo names a function template, and foo<int> would name a specialisation of that function template and is a function)
Both of the statements apply at once. They both say 'if these conditions are not met the program is ill-formed', not that 'if these conditions are met the program is not ill-formed'.
So, [temp.pre]/10 would not make this program ill-formed, because there is a corresponding explicit instantiation. But [basic.def.odr]/11 makes this program ill-formed anyways because foo<int> is an inline function.