+2  A: 

You have to provide a template arguments for all Forest parameters.

template<typename NODETYPE>
Forest<NODETYPE> operator+(Forest<NODETYPE>& f1, Forest<NODETYPE>& f2)

Also, consider making the arguments const references to make sure you do not manipulate them.

There are several questions on stackoverflow regarding friend function templates. The C++ FAQ also has a page on them that explains some basics.

Space_C0wb0y
And remove `<>`. His code is bad, though, so he cannot make them const references.
GMan
Ahh, thanks. I would do that, but the project requirements are that the arguments be deleted afterwards, for some reason.
joedillian
@joedillian: This is bad. Operator overloading is a double edged sword in that it often leads to code that is hard to understand if operators behave unintuitively. Noone expectes `+` to delete the operands.
Space_C0wb0y
@joe: Don't let your project requirements influence you outside the project, for your own good. And kick whoever made them for me.
GMan
I agree, but professor's function behavior delcares it to act as such. Meh.
joedillian
@joedillian: Send him our way. Guy doesn't know what he's talking about...gr.
GMan
@GMan: As long as the operator+ in OP does not modify 'root' it is fine. I am not sure if I understand your comment right. It is OK to modify *f1.root even if f1 is passed as reference to const. Isn't it?
Chubsdad
Thanks for those references in your edit Space_Cowboy. I wish I had found that when i was searching the net for 2 hours. :-/
joedillian
+2  A: 

why are you putting <> behind the operator name?

DaVinci
Hmm. Because i found a reference somewhere else that said that lets the compiler know it is a template function. Guess that was pretty wrong.
joedillian
A: 

You can define an operator+ template as follows:

template< class NodeType >
Forest<NodeType> operator+( Forest<NodeType> const& f1, Forest<NodeType> const& f2)
{
    // Implementation.
}

Cheers & hth.,

Alf P. Steinbach
+2  A: 

The key to writing operator+ is don't write operator+. Instead, write a copy ctor and operator+=:

template<class NodeType>
struct Forest {
  //...
  Forest(Forest const &other);
  //...
  Forest& operator+=(Forest &other) {
    // code here
    return *this;
  }
  //...
};

Now we add operator+:

template<class NodeType>
struct Forest {
  //...
  friend Forest operator+(Forest a, Forest const &b) {
    a += b;
    return a;
  }
  //...
};

And that's it! Copying is usually straight-forward (sometimes by being disallowed) and it may be simpler to think in terms of += than + (you have two objects and mutate one, rather than create a third object out of two). This pattern for op+ works with any similar type, and even for similar operators such as -, *, and /.

Roger Pate
Taking the first parameter by value instead of const reference is useful as we're going to copy it anyway, but b should be taken as const-reference.
CashCow
@CashCow: You're absolutely right and that's what I intended; it's rather late here, so if you find any more errors, you'll have to wait. :)
Roger Pate
Note to those passing by, it may be tempting to make that `return a += b`, but this is enough to fool the compiler from treating the result of `a += b` the same as `a`, so no NRVO is applied (and in C++0x, it is not moved.) You can of course do `return std::move(a += b);` to help it out, but you're not really gaining anything.
GMan
+1  A: 

Operator overloading can be a good or a bad thing. Good when it leads to simpler looking code. Bad when it leads to writers either overloading with incorrect semantics (yet a solution that compiles) or where the intuitive way to use the operator leads to highly inefficient code.

Note the latter statement can apply to std::string too, which could potentially make large numbers of copies, and which is why the standard states that a string does not have to be stored internally in a contiguous buffer (in the old days they used copy-on-write references to and could store such references to both strings being concatenated until required. Subsequently it was found to be non-threadsafe and making it so was more costly than simply copying the buffer so now they copy every time and are inefficient again).

The correct signature of operator+ (in the case all are the same type) is as follows:

T operator+( const T&, const T& );

As a member function it would be:

class T
{
    // make public if necessary
    T operator+( const T& rhs ) const;
};

You can implement operator+ automatically as a template whenever operator += is available with

template<typename T, typename R>
T operator+( const T& lhs, const R& rhs )
{
    T copy(lhs);
    return copy += rhs;
}

If you want to declare an overloaded operator of your template as a friend, this is the correct way to do it. I will show it with operator<<

// first some forward declarations, assume ostream already declared with #include <iosfwd> minimum
template< typename T > class Forest;
template< typename T > std::ostream & operator<<( std::ostream & os, const Forest<T> & for );

template< typename T> class Forest
{
     friend std::ostream& operator<< <>( std::ostream&, const Forest<T> & );
     //rest of class Forest
};

template< typename T >
std::ostream & operator<<( std::ostream& os, const Forest<T> & forest )
{
    // implement
    return os;
}

You would apply a similar technique to any other external function you wish to declare as a friend to your class, i.e.

  1. Forwardly declare your class as a template
  2. Forwardly declare the method as a template function
  3. Make the function a friend using <> before the opening parentheses denoting the parameters
  4. Implement the function after your class.
CashCow
Friend functions for op<<, defined in the class definition, are much easier.
Roger Pate