1

The following code works fine:

struct A {
    int d;
    A(int _d) : d(_d) {}
};
A operator+(const A& x, const A& y) {
    return x.d + y.d;
}
int main() {
    A x = 6;
    cout << (x + 4).d << endl;
    cout << (4 + x).d << endl;
}

However, if I make A a template class, then it doesn't compile:

template<int p>
struct A {
    int d;
    A(int _d) : d(_d) {}
};
template<int p>
A<p> operator+(const A<p>& x, const A<p>& y) {
    return x.d + y.d;
}
int main() {
    A<0> x = 6;                // OK
    cout << (x + 4).d << endl; // error: no operator found or there is no acceptable convertion
    cout << (4 + x).d << endl; // error: no operator found or there is no acceptable convertion
}

It works when I do explicit convertion A<0>(4) or (A<0>)4, but it's annoying.

I would like to know what causes this difference between "normal" and "template" classes, and how can I get implicit convertion working.

I'm using MSVC compiler, if that matters.

WhatsUp
  • 1,618
  • 11
  • 21
  • @Eljay Thanks, I added the tag according to your suggestion. – WhatsUp Apr 15 '22 at 14:04
  • 1
    Does it work if you define the operator as a friend inside the class definition (instead of standalone)? – bobah Apr 15 '22 at 14:10
  • I think it's because the compiler can't deduce what the template argument for conversion of the `int` constants to an `A` should be. Same as if you try: `A x = 6;`, giving *error : no viable constructor or deduction guide for deduction of template arguments of 'A'* – Adrian Mole Apr 15 '22 at 14:11
  • 2
    Template argument deduction doesn't consider implicit conversions. – Jason Apr 15 '22 at 14:13
  • @bobah Yes, it mysteriously works! So why is this happending? It all looks very subtle to me. – WhatsUp Apr 15 '22 at 14:16
  • @WhatsUp - see the AnoopRana answer above. – bobah Apr 15 '22 at 14:18

1 Answers1

1

The problem is that template argument deduction doesn't consider implicit conversions like the one converting constructor that you've provided.

From template argument deduction's documentation

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.

Jason
  • 36,170
  • 5
  • 26
  • 60