Considering two ways to create a non-member operator+ for A , we can either make it a function template:
template <int x> int operator+(A<x>, int);
which will not match B<x> , because we simply draw the output of a template that does not allow conversion.
Or we can make it a friend without a template:
template <int x> struct A { friend int operator+(A a, int ); };
which will also not match B<x> , because a name lookup will not consider this function. If, say, we do not say:
template <int x> struct B { friend int operator+(A<x>, int );
Now the original non-template operator+ will be considered, the conversion will be performed as desired, and your code will print 29.
Barry source share