Let's start with a simple add method for class number
:
class number {
int num;
public:
number(int num = 0): num(num) {}
operator int() const { return num; }
};
number add(number t1, number t2) {
return t1 + t2;
}
int main() {
auto result1 = add(1, 2); // auto-casting, works fine
}
Now we want to turn number
into a template class:
template<class T>
class number {
T num;
public:
number(T num = 0): num(num) {}
operator T() const { return num; }
};
template<class T>
number<T> add(number<T> t1, number<T> t2) {
return t1 + t2;
}
Trying to call add
the same as we called the simple non-templated one, based (theoretically!) on CTAD:
int main() {
number a = 3; // works, using CTAD
// auto result1 = add(1, 2); // <== what we wish for, but can't find method
// auto result2 = add(a, 2); // this also doesn't work, no ADL here :(
auto result3 = add<int>(1, 2); // this works, but is not what we wish
}
Note that if add
was a friend function, calling it with one of the parameters being a number
would work, based on ADL:
template<class T>
class number {
T num;
public:
number(T num = 0): num(num) {}
operator T() const { return num; }
friend number add(number t1, number t2) {
return t1 + t2;
}
};
int main() {
number a = 3; // works, using CTAD
auto result1 = add(a, 2); // works, based on ADL
// auto result2 = add(1, 2); // still doesn't work, no ADL here :(
}
Any suggestion how to allow the template class to behave similarly to the non-template, having auto casting when calling add?
EDIT:
This question was edited based on posted comments. It should be emphasized that for a generic function like add
having such an auto casting might be a wrong idea, but suppose that the method is very specific, something like doSomethingWithNumbers
.