
AMDG Niels Dekker - address until 2010-10-10 wrote:
Steven Watanabe wrote:
I don't think that non-template friends should be defined inline in a class template because they are always supposed to be instantiated regardless of whether they are used or not (unlike ordinary members).
Thanks, Steven. Do I understand correctly that when you look at the following example, you find the definition of operator+ preferable to operator- ?
////////////////////////////////////////////////////////// template <typename> class safe_int;
template <typename T> safe_int<T> operator+(safe_int<T>, safe_int<T>);
template <typename T> class safe_int { public: friend safe_int operator+ <>(safe_int, safe_int);
inline friend safe_int operator-(safe_int, safe_int) { throw "operator- not yet implemented."; } };
template <typename T> safe_int<T> operator+(safe_int<T>, safe_int<T>) { throw "operator+ not yet implemented."; } //////////////////////////////////////////////////////////
I still hesitate, because the non-template inline friend, operator-, appears to support implicit conversions more intuitively... I think.
Sorry. I reacted automatically, because of the problems that I've had with inline friends. In this case, I think it's not a problem to define them inline. The cases that cause problems are like: template<class Iterator> struct reverse_iterator { friend reverse_iterator operator+(typename Iterator::difference_type n, reverse_iterator iter) { return(reverse_iterator(iter.base() - n)); // oops... early error if Iterator is not a RandomAccessIterator } }; For safe_int, you could only run into problem by both a) supporting user-defined type. I don't see the point of this. b) only requiring the underlying type to support division (e.g.) if the user tries to divide two safe_ints.
Isn't support of such conversions (in a symmetrical way) the main reason to declare such operators as non-members, rather than as member functions?
Maybe. For me it's more important that the operators are defined consistently and there is no way to overload an operator as a member with the first argument being of a different type. In any case, it's okay to support implicit conversions for both arguments or neither, as far as I am concerned. It's the matter of supporting implicit conversions only for the second argument that makes the member operator really unattractive. In Christ, Steven Watanabe