https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83145
--- Comment #3 from Luboš Luňák <l.lunak at centrum dot cz> --- You are right, it is controlled by the -fnew-ttp-matching option. But while I admit I have a problem deciphering what the referenced paper says in practice or how it exactly applies to this case, this still looks broken to me. Consider the following case, which is the original reduced to just one template argument instead of 3: ===== template <typename... TValues> class Variant { }; class BinaryOutputStream { }; template <typename... TValues> BinaryOutputStream& operator<<(BinaryOutputStream& stream, const Variant<TValues...>& /*variant*/) { return stream; } template <template <typename T> class TCollection, typename T> BinaryOutputStream& operator<<(BinaryOutputStream& ostream, const TCollection<T>& /*arr*/) { return ostream; } int main() { Variant<float> variant; BinaryOutputStream stream; stream << variant; return 0; } ===== That still triggers the error. Now remove the use of the variadic template (i.e. remove those 3 cases of "..."), and now it compiles just fine. Why should the use of a variadic template make any difference here? To me the Variant overload looks like an obviously better match in both cases.