How to define non-member operator overload for class template?
The simpler way is to put the function in the class:
template <int n> struct MyClass {
MyClass() = default;
template <typename REP, typename PERIOD>
constexpr MyClass(const std::chrono::duration<REP, PERIOD> &d) noexcept
: num(d.count()) {}
friend bool operator==(MyClass lhs, MyClass rhs) { return lhs.num == rhs.num; }
int num = n;
};
Demo
This doesn't work:
if (m1 == 10ns)
because when we're doing lookup on operator==
between MyClass<0>
and std::chrono::duration<???, std::nano>
, the only operator we find is:
template <int n>
bool operator==(MyClass<n> lhs, MyClass<n> rhs);
This isn't a match - 10ns
is not a MyClass<n>
for any n
, so template deduction fails. To write a non-member equality operator, you would need to match against any duration:
template <int n, class R, class P> bool operator==(MyClass<n>, duration<R,P> );
in both directions:
template <int n, class R, class P> bool operator==(duration<R,P>, MyClass<n> );
In addition to the operator you already have. That would work, and is sometimes even necessary.
A simpler approach would be to declare your operator==
as non-member friend, as Jarod42 suggests. The reason this works is that where your non-member function was a function template, the friend is not. So lookup on m1 == 10ns
finds the function:
bool operator==(MyClass<0>, MyClass<0>);
10ns
is convertible to MyClass<0>
, which is allowed in this context, so this works. That conversion is very cheap, so no worries there. And you just have to write the one function.