A simple way to reproduce your issue:
int main()
{
using namespace N;
std::cout << std::endl;
}
In this case, candidate functions are all overloads of operator<<
from namespace std
, all member operator<<'s from std::ostream
, and your function template operator<<
from namespace N
.
13.3.1/7: "where a candidate is a function template, candidate function template specializations are generated using template argument deduction"
So, before overload resolution can begin, X<types...> const&
has to be deduced from std::endl
, which is an address of a template function. Address of a function is a function pointer type, and the only way to match N::X<types...> const&
to a pointer type is to deduce types...
as an empty list.
(substitution of course fails since there is no implicit conversion from any function pointer type to N::X<>
, which would have eliminated the overload quietly as non-viable, but the static assert is not in immediate context and is a hard error)
The moral of the story: using-directives are evil.