Если вы можете изменить builtin_max
, то путь состоит в том, чтобы изменить сигнатуру так, чтобы она брала две константные ссылки и возвращала константную ссылку (если тип не является достаточно маленьким, чтобы передача по значению имела смысл), и перегрузка для неконстантной версии. Тогда вы можете легко адаптировать подписи: просто переадресовать звонок.
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 );
}
Еще одна простая вещь, которую вы можете сделать, это не перегрузить std::max
, а создать собственную функцию max
в вашем пространстве имен. Все неквалифицированные использования max
, которые принимают значения fract
, найдут вашу функцию max
, прежде чем они попытаются использовать шаблон std::max
по умолчанию. Опять же, это не будет работать для полностью квалифицированных звонков на 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
}