https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103250
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> --- I don't think this is a bug. You've added an overload and it's not more specialized than the function defined by the standard library: operator/ (const valarray<T>&, const valarray<T>&) The compiler is correct to reject it as ambiguous. The unpreprocessed code is: #include <valarray> namespace qaz { namespace traits { template < typename T, typename Q1, typename Q2 > struct div_type { typedef div_type type; }; template < typename T, typename Q > struct div_type<T,Q,Q> { typedef T type; }; } template < typename T, typename Q1, typename Q2 > using div_type = typename traits::div_type<T,Q1,Q2>::type; template < typename T, typename Q > struct num { }; template < typename T, typename Q1, typename Q2 > auto operator/( const num<T,Q1> &, const num<T,Q2> & ) -> div_type<T,Q1,Q2>; template < typename T, typename Q1, typename Q2 > auto operator/( const std::valarray< num<T,Q1> > &x, const std::valarray< num<T,Q2> > &y ) -> std::valarray< decltype(x[0]/y[0]) >; } template < typename T, typename Q > auto f( size_t n ) { std::valarray< qaz::num<T,Q> > x(n); return x/x; } struct tag {}; template auto f< int, tag >( size_t ); You can fix it by adding another overload which will be more specialized: template < typename T, typename Q1 > auto operator/( const std::valarray< num<T,Q1> > &x, const std::valarray< num<T,Q1> > &y ) -> std::valarray< decltype(x[0]/y[0]) >;