г cc правильно; это связано с тем, что в режиме C ++ 17 он реализует разрешение DR P0522 до CWG 150 , позволяя игнорировать параметры шаблона по умолчанию при сопоставлении параметра шаблона шаблона:
template <template <typename> class> void FD();
template <typename, typename = int> struct SD { /* ... */ };
FD<SD>(); // OK; error before this paper (CWG 150)
Другие компиляторы (пока) не реализуют P0522 и поэтому не видят перегрузку generi c как жизнеспособную.
При условии, что она жизнеспособна, и в соответствии с правилами для частичного упорядочения функции В шаблонах в C ++ 17 ни один соответствующий второй аргумент не может быть выведен из другого (Container<T, Alloc>
против std::unordered_set<K, Hasher, Keyeq, Alloc>
), поэтому перегрузки неоднозначны. Решение, которое упомянул в комментариях, состоит в том, чтобы сделать перегрузку generi c более обобщенной c, так что std::unordered_set<K, Hasher, Keyeq, Alloc>
может быть выведена на нее; например :
template <typename T, class... Ts, template<typename, class...> class Container>
Stream & operator<< (Stream &stream, const Container<T, Ts...>& container)
Здесь std::unordered_set<K, Hasher, Keyeq, Alloc>
выводит до Container<T, Ts...>
(с Container = std::unordered_set
, T = K
, Ts = {Hasher, Keyeq, Alloc}
), поэтому перегрузки могут быть частично упорядочены.
Это должно работать как в C ++ 14, так и в C ++ 17 и более поздних версиях.