3

The following non-template code works well:

struct A { };

struct B
{
    B() {}
    B(const A&) {}
    friend B operator+(const B&) { return B(); }    
};

B operator+(const B&);

int main()
{
    A a;
    B b;
    +b;
    +a;
}

But if I make classes in this code templated:

template <class T>
struct A { };

template <class T>
struct B
{
    B() {}
    B(const A<T>&) {}
    friend B operator+(const B&) { return B(); }    
};

template <class T>
B<T> operator+(const B<T>&); // not really what I want 

int main()
{
    A<int> a;
    B<int> b;
    +b;
    +a;
}

some kind of troubles appear:

error: no match for 'operator+' (operand type is 'A<int>')

Is it possible to declare non-template friend function for template class outside the class (as I did for non-template classes above)?

I can solve the problem by adding template operator for A<T> argument and call friend function inside, but it is not interesting.

UPD:

Another workaround (inspired by R Sahu's answer) is add friend declaration for class A:

template <class T>
struct A { 
    friend B<T> operator+(const B<T>&);
};

but this gives a warning, and I don't know how to fix it correctly.

Community
  • 1
  • 1
αλεχολυτ
  • 4,792
  • 1
  • 35
  • 71
  • I am not sure what you desire to have. B is a template here, so you need a template parameter to operate on it. What should the template parameter be if it is not dynamically determined? – IceFire Mar 15 '16 at 20:56
  • @IceFire what kind of `dynamically` do you mean? – αλεχολυτ Mar 16 '16 at 08:21

2 Answers2

1

Is it possible to declare non-template friend function for template class outside the class (as I did for non-template classes above)?

Yes, it is possible. However, what you probably need is a function template too, and make sure that operator+<int> is a friend of A<int>, operator+<double> is a friend of A<double>, etc.

See https://stackoverflow.com/a/35854179/434551 to understand how that can be done.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Adding a `friend` declaration for class `A` works. But a [warning appears](http://coliru.stacked-crooked.com/a/25b9a295a2870eb9). – αλεχολυτ Mar 16 '16 at 05:26
  • @alexolut, The warning message makes sense. The function `B operator+(const B&);` has not been declared to be function template before it is made a `friend` of `A`. Take a look at a simplified version that does not use `A`: http://ideone.com/U5EJPp. And another version that has `A` but does `A` is not doing much: http://ideone.com/WjpxyY. – R Sahu Mar 16 '16 at 05:42
  • A second version does not use `a` object. If I add it - I got [same error](http://coliru.stacked-crooked.com/a/41021d01e4013662) as in original question. N.B. ideone does not show any warnings if no errors occured. – αλεχολυτ Mar 16 '16 at 06:15
  • @alexolut, I took out the line that had `+a` since it is an undefined function. `B operator+(const B&);` only supports the unary `+` operator on `B`, not on `A`. – R Sahu Mar 16 '16 at 06:16
  • but there is implicit conversion from A to B by B's ctor, and my desire is to make it works (like in example of non-template version of A & B) – αλεχολυτ Mar 16 '16 at 06:27
  • @alexolut, implicit conversion is not performed when deducing typenames of function templates. That's why `+b` works but `+a` does not. – R Sahu Mar 16 '16 at 06:28
  • But it works when I declare friend inside A. Is not it? – αλεχολυτ Mar 16 '16 at 06:34
  • @alexolut, no it does not. – R Sahu Mar 16 '16 at 06:35
  • Are you sure? Implicit conversion [works](http://coliru.stacked-crooked.com/a/58fb6a77b4be1b00). – αλεχολυτ Mar 16 '16 at 08:14
0

Is it possible to declare non-template friend function for template class outside the class?

Answer: yes, but... you need to declare a function for each one combinations you use:

This funcion solves the problem for your puntual declaration:

A<int> operator+(const A<int>&) { return A<int>(); }

But, if you use A< double>, you need to explicity declare other function:

A<double> operator+(const A<double>&) { return A<double>(); }

Is not requiered friend because in a struct all member are public

Ing. Gerardo Sánchez
  • 1,607
  • 15
  • 14
  • My question is about **declaration** only, not definition. The only one definition of `operator+` positioned inside class's `B` definition, and I don't want to add any other overloading functions. `friend` is necessary here for implicit argument conversion, not for accessing private members. See [here](http://stackoverflow.com/questions/8890051/implicit-conversion-when-overloading-operators-for-template-classes) & [here](http://stackoverflow.com/questions/381164/friend-and-inline-method-whats-the-point). – αλεχολυτ Mar 16 '16 at 05:16