There was a discussion about function specialization here: Will specialization of function templates in std for program-defined types no longer be allowed in C++20?
In principal I understand, that it is better to overload instead of specialize. But how do you overload a std function template properly? The canonical answer seems to be: just overload in your custom namespace and then ADL kicks in. But this doesn't work, if fundamental types are involved. Non-working example:
#include <cmath>
namespace X {
class Y { };
Y sqrt(Y);
double foo(double x) { return sqrt(x); }
}
The example will only compile without the sqrt declaration for Y. One can solve the issue by overloading in namespace std instead:
#include <cmath>
namespace X {
class Y { };
}
namespace std { X::Y sqrt(X::Y); }
namespace X {
double foo(double x)
{
return sqrt(x);
}
}
This code does exactly what I want to do. However I am unsure, if this kind of overloading is permitted by the standard. At cppreference I don't find a hint toward this direction. And while this paper of Walter E. Brown proposes overloading as an alternative to specialization, I am unsure, if the above example uses it right (the paper doesn't give any examples).
Adding overloads of sqrt to the std namespace is not permitted.
You can however either use the fully qualified name, or give std::sqrt preference by adding using std::sqrt:
#include <cmath>
namespace X {
class Y { };
Y sqrt(Y) { return {}; }
double foo(double x) {
return std::sqrt(x);
}
} // namespace X
template <typename T>
T bar(T x){
using std::sqrt;
return sqrt(x);
}
double baz(double x){
using std::sqrt;
return sqrt(x);
}
double moo(double x){
return bar(x);
}
X::Y zoo(X::Y x){
return bar(x);
}
Note that std::sqrt disables ADL, while using std::sqrt still allows ADL to kick in, as exemplified by bar which is called from moo and zoo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With