If you can modify the builtin_max
then the way to go is changing the signature so that it takes two constant references and returns a constant reference (unless the type is small enough that pass-by-value makes sense), and overload for the non-const version of it. Then you can adapt the signatures the easy way: just forward the call.
fract const & builtin_max( fract const & lhs, fract const & rhs );
fract & builtin_max( fract & lhs, fract & rhs );
template <>
fract const & std::max( fract const & lhs, fract const & rhs ) {
return builtin_max( lhs, rhs );
}
template <>
fract & std::max( fract & lhs, fract & rhs ) {
return builtin_max( lhs, rhs );
}
Another simple thing that you can do is not overload std::max
but rather produce your own max
function within your namespace. All unqualified uses of max
that take fract
values will find your max
function before they try to use the std::max
default template. Then again, this will not work for fully qualified calls to std::max
:
namespace x {
class fract;
fract max( fract lhs, fract rhs ) { return builtin_max( lhs, rhs ); }
}
// force a link time error if fully qualified std::max is used (undefined)
// instead of silently getting std::max to use < (if it is defined)
// if there is no operator<( fract const &, fract const & ), leave this out
// to get an earlier compile time error
template <> fract const & std::max( fract const &, fract const & );
template <> fract & std::max( fract &, fract & );
int main() {
using namespace std;
fract a,b;
max( a, b ); // x::max
// std::max( a, b ) // ouch, link time error
}