Reputation: 2005
I like to play with auto and decltype, and then I wondered if it would be possible to do generic operators with auto. Indeed, since c++14 et can do this:
decltype(auto) add(auto v1, auto v2) {
return v1 + v2;
}
however, I wanted to try it with templated classes containing values like this one:
template<typename T>
class test {
public:
T value;
test(T val) {
value = val;
}
};
and then I would need an overloading operator + like this one which work:
template<typename T>
T operator+(test<T> const& t1, test<T> const& t2) {
return t1.value + t2.value;
}
which is already quite great. However, I would like a generic operator+ which can be use by multiple classes. Like these one:
decltype(t1.value) operator+(auto const& t1, auto const& t2) {
return t1.value + t2.value;
}
template<typename T>
T operator+(auto const& t1, auto const& t2) {
return t1.value + t2.value;
}
which doesn't not compile.
In C++14/17, is there a way to make generics overloading operators which would be able to be used by many classes like the ones I wrote ?
PS: here the code for your tests which compile with gcc7 snapshot but not with clang which seems to don't allow the auto in functions prototypes : link to compiler explorer code
#include <iostream>
template<typename T>
class test {
public:
T value;
test(T val) {
value = val;
}
};
template<typename T>
T operator+(test<T> const& t1, test<T> const& t2) {
return t1.value + t2.value;
}
decltype(auto) add(auto v1, auto v2) {
return v1 + v2;
}
int main() {
decltype(5) v1 = 5;
decltype(v1) v2 = 3;
test<decltype(v1)> t(v1);
test<decltype(v2)> t2(v2);
return add(t, t2);
}
Upvotes: 2
Views: 311
Reputation: 37616
If I understood your question, you can use a trailing return type:
auto operator+(auto const& t1, auto const& t2) -> decltype(t1.value + t2.value) {
return t1.value + t2.value;
}
For compiler that do not accept auto
for parameters, you can simply fall backs to two template parameters:
template <typename U, typename V>
auto operator+(U const& t1, V const& t2) -> decltype(t1.value + t2.value) {
return t1.value + t2.value;
}
As @Jarod42 mentioned in the comments, you probably want to use decltype(t1.value + t2.value)
instead of decltype(t1.value)
to handle conversions and promotions correctly.
Upvotes: 3