Well, there is one thing to take into consideration. The above will establish a one-to-many relationship between a class instance and the operator+() function. That is, for each Int object all instantiations of operator+() are friends.
So you can incur in unwanted behavior when you try to do something like this:
Code:
Int<int> a(4);
Int<double> b(5);
Int <float> c(0);
c = a + b;
It may be ok. You may want the implicit conversions. If you do not want this behavior you must establish a one-to-one relationship in which each class instantiation maps only to one function instantiation with the same template argument.
For that, you have to revert to the way you had your code in the initial post. Then you first need to make a declaration of the function before the class definition...
Code:
template <typename T>
Int<T> operator +(const Int<T>&, const Int<T>&);
template <typename T>
class Int
{
/*... */
This guarantees that the function declared inside the class is already known to the compiler. The name is in scope. However, you will now get an error on that function declaration line complaining about Int not being declared... So we forward-declare it...
Code:
template <typename T>
class Int;
template <typename T>
Int<T> operator +(const Int<T>&, const Int<T>&);
template <typename T>
class Int
{
/*... */
And then we get an error complaining about the function inside the class being declared as non-template (again!). So... we declare it as a template with an empty pair of ... whatever those signs are called....
Code:
template <typename T>
class Int;
template <typename T>
Int<T> operator +(const Int<T>&, const Int<T>&);
template <typename T>
class Int
{
T x;
public:
Int(int);
Int(const Int<T>&);
Int<T>& operator =(const Int<T>&);
friend Int<T> operator +<>(const Int<T>&, const Int<T>&);
void show()
/ *... */
And so it is. Now if you try the following code you don't even need to wait for a run-time error. The compiler will immediately warn you.
Code:
Int<int> a(4), b(5);
Int<float> c(0);
c = a+b; // compiler issues error here.
EDIT: Keeping this post because... well, it still has its uses. However while correct, the premise is wrong. You will not face the problem of unwanted conversions because there's one 1 template parameter that maps to both the function arguments and the return type. The compiler will always complain. You don't need the text on this post. Sorry about that. Wasn't thinking.