C++ Template no match for operator<

I've seen questions similar to this, but haven't found a solution that worked on my problem, so I was hoping I could get some help.

I want to pass a class as an argument to a function with template parameters (For this example I just want it to compile, so nvm that it doesn't make sense with return true in operators). I figured this way in the following code would work:

template<typename T>
class MyClass {
public:
    bool operator>(const T&) const { 
        return true;
    }  

    bool operator<(const T&) const { 
        return true;
    }
};

template<typename T, typename S> 
vector<T> between_interval(T* start, T* end, const S& low, const S& high){
    vector<T> vec;
    for ( ; start != end; start++) {
        if (low < *start && *start < high)
            vec.push_back(* start);
    }
    return vec;
}

int main() {
    double v1[] = {1.23, 4.56, 7.89, -10, 4};
    MyClass<double> k1;
    MyClass<double> k2;
    vector<double> res = between_interval(v1, v1 + 3, k1, k2);
    for (auto x : res)
        cout << x << " ";
        cout << endl;
    } 

I get the following error(s):

u4.cpp: In instantiation of ‘std::vector<T> between_interval(T*, T*, const S&, const S&) [with T = double; S = MyClass<double>]’:
u4.cpp:39:55:   required from here
u4.cpp:28:36: error: no match for ‘operator<’ (operand types are ‘double’ and ‘const MyClass<double>’)
     if (low < *start && *start < high)

I realize passing K1 and K2 won't make sense as it is at the moment, but the compiler doesn't mention this, it complains about not having a match for operator<, so my main question is why? Is it too general with a template argument in operator<? Is there any other way to make the operators work but without using the templates?

Thank you

Upvotes: 1

Views: 1882

Answers (3)

Jarod42
Jarod42

Reputation: 217283

With

template<typename T>
class MyClass {
public:
    bool operator>(const T&) const { 
        return true;
    }  

    bool operator<(const T&) const { 
        return true;
    }
};

and

MyClass <double> k1;
double d = 4.2;

you might do

  • k1 < d
  • k1 > d

but you do

  • d < k1 (with *start < high)

you have to implement that operator too or change the code to use the provided operator.

Upvotes: 4

NathanOliver
NathanOliver

Reputation: 180630

Because your operator < is a member function it expects the left hand operand to be of the class type. That is fine for low < *start but in *start < high you have a double as the left hand operand.

You will either need to provide a free function that takes a double as the first parameter or make your class convertible to a double (or T).

Upvotes: 4

Fran&#231;ois Andrieux
Fran&#231;ois Andrieux

Reputation: 29022

Member operators always use the left operand as this and the right operand as the operator argument. That means your comparison operators will only work when the MyClass is on the left of the comparison. The quick fix is to change the line if (low < *start && *start < high) to if (low < *start && high > *start) to put the MyClass instance on the left side of each comparison. The cleaner solution is to provide free operators which take a T on the left side and a MyClass<T> on the right side. For example :

template<typename T>
bool operator>(const T& p_left, const MyClass<T> & p_right) {
    return p_right < p_left;
}

template<typename T>
bool operator<(const T& p_left, const MyClass<T> & p_right) {
    return p_right > p_left;
}

Upvotes: 2

Related Questions