Reputation: 61
template< typename _Type >
struct TypeChecker {};
template< typename _Type >
bool f0( _Type obj )
{
return TypeChecker< _Type >::value;
}
struct S {};
void f1()
{
f0( S{} );
}
template<>
struct TypeChecker< S > : std::true_type {};
Obviously "TypeChecker< S > : std::true_type" is not known at the point f1() is defined, but both of MSVC2019 and Clang compiles this without an error.
What I'm not sure is if this is guaranteed behavior by standard.
I found a few similar questions in SO: When is a C++ template instantiation type checked? Incomplete class usage in template Can the point-of-instantiation be delayed until the end of the translation unit?
And I believe this is the relevant part from the spec:
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 the translation unit, the end of the translation unit is also considered a point of instantiation.
But what exactly "the end of the translation unit is also considered a point of instantiation" means? Does this mean it's implement dependent? Like "compiler A" compile above code without an error and "compiler B" doesn't, while both are standard conforming?
Or is this code guaranteed to be well-formed by any standard c++ compilers?
Upvotes: 1
Views: 111
Reputation: 39758
Your program is ill-formed, no diagnostic required, because the explicit specialization is not defined before the (first) place where it is (or would be) implicitly instantiated. The point of instantiation business is something of a red herring: that governs name lookup, not validity (except that it’s also ill-formed NDR to have the results of that lookup depend on which of multiple points of instantiation is chosen).
Upvotes: 1