c++ - Overloading of template function in template class -


i have templated operator in templated class , want change behavior specific type. code:

#include <iostream>  template <typename n> struct {   int x;   template<typename t>   a& operator<<(const t& t) {     x += static_cast<int>(t);     return *this;   } };   enum class b {   s,t };  template <typename n> a<n>& operator<<(a<n>& a, const b& b) {   a.x -= static_cast<int>(b);   return a; }  int main() {   a<int> a{3};   std::cout << (a<<1).x << " " << (a << b::s).x; } 

g++-4.9 compiles fine clang-3.6 complains it's ambiguous.

note, if class not templated, both of compilers compile fine.

what correct behavior?

short summary: believe gcc bug in template partial ordering rules, , clang correct. filed bug 66914, although it's duplicate of bug 53499 didn't notice until afterwards.


in call

a << b::s; 

we have 2 viable candidates:

template <typename t> a<int>::operator<<(const t& ); template <typename n> operator<<(a<n>&, const b& ); 

you can rewrite member function take reference instance first argument, , write out both instantiatons. have:

template <> operator<<(a<int>&, const b& ); // [t = b] template <> operator<<(a<int>&, const b& ); // [n = int] 

since both viable candidates, let's go through rules in [over.match.best] determine 1 best viable candidate:

given these definitions, viable function f1 defined better function viable function f2 if arguments i, icsi(f1) not worse conversion sequence icsi(f2), , then

— argument j, icsj(f1) better conversion sequence icsj(f2), or, if not that,

nope, both take exact same arguments, conversion sequences identical.

— context initialization user-defined conversion [ ... ]

nope, irrelevant.

— context initialization conversion function [ ... ]

nope, irrelevant.

— f1 not function template specialization , f2 function template specialization, or, if not that,

nope, both function template specializations.

— f1 , f2 function template specializations, , function template f1 more specialized template f2 according partial ordering rules described in 14.5.6.2.

this complicated of rules. ultimately, neither more specialized other. why? member function effectively:

template <typename t> a<int>& operator<<(a<int>&, const t& ); 

if synthesized type t (call unique1), deduction fail against free function (since unique1 wouldn't match b). on other side, if synthesized type n (call unique2), deduction fail against member function (since unique2 wouldn't match int).

since neither function more specialized other, we've run out of bullet points. function call should ambiguous, gcc bug.


Comments