Question

Id like to say that there's a ton of C++ Overloading questions already on SO, but after an hour of looking at them and other posts on forums and newsgroups, I'm still stumped.

Background

I've created a namespace, call it A, where a bunch of classes have the same way of implementing the < operator. In order to avoid code duplication, I wrote this:

namespace A{
     template<typename T>
     bool operator< (const T&, const T&);
}

In a header file called operator_forwards.h along with a few other declarations. I then made it a friend to the correct classes by adding a line like this:

//example.h
#include "operator_forwards.h"
namespace A{
    template<typename T>
    class Example{
        public:
        friend bool operator< <>(const Example<T>&, const Example T&);
        private:
        T start;
    };
} 

Finally, I put the definition in a file called operators.h like this:

namespace A{
    template<typename T>
    bool operator<(const T& lhs, const T& rhs){
        using std::operator<;
        return lhs.start<rhs.start;
    }
}

And included everything in one header file:

//A.h
#include "example.h"
#include "operators.h"

The Problem

The problem is when I call operator< like this:

Example<vector<int>::iterator> ex1(**foo**);
Example<vector<int>::iterator> ex2(**bar**);
ex1<ex2;

It calls A::operator< fine, however it recursively calls itself to do ex1.start<ex2.start rather then looking up the more specialized operator< for vector::iterator. Resulting in the error C2039: start is not a member of vector::iterator.

Does anyone have any advice for making sure that A::operator< calls the correct operator< for ex1.start?

Note: there are about 20 classes that use A::operator< so if I could avoid defining it in each class separately that'd be awesome.

Was it helpful?

Solution

My humble suggestion: don't do that.

You'll have to deal with this problem in more places than the implementation of A::operator<. Any code anywhere in A can potentially get bamboozled by this unexpected template which claims to support operator< for anything, but can only actually perform it on types which have a start member.

In your case, you're putting a friend declaration in every relevant class anywhere. It's barely any more code to simply implement it in those classes. If that offends your code-duplication sensibilities, then consider a shared base class:

template <typename T>
class IterWrapper {
public:
    IterWrapper() {}
    explicit IterWrapper(T it) : start(it) {}

    bool operator< (const IterWrapper<T>& rhs) { return start < rhs.start; }
protected:
    T start;
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top