How can I return a temporary from my specialized std::max?
Hallo!
I want to specialize std::max
for a platform-specific fraction type.
The prototype for the system-specific max
I want to use looks lik开发者_运维知识库e this:
fract builtin_max(fract a, fract b);
My idea for a specialized std::max
looks like this:
template <> inline
const fract& std::max<fract>(const fract& a, const fract& b) {
return builtin_max(a, b);
}
However, the compiler understandably complains about returning a reference to a local temporary. Is there any way I can work around this?
You could return a result by value. Then RVO most likely will take place. In the end you will get behavior as you wanted.
And I'd change builtin_max
declaration to
fract builtin_max(const fract& a, const fract& b);
It will help to the compiler to recognize the possibility for RVO.
Finally your max
will look like:
template <>
fract std::max<fract>(const fract& a, const fract& b) {
return builtin_max(a, b);
}
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
}
My solution was to do it just like this:
fract std::max(fract a, fract b) {
return builtin_max(a, b);
}
Super simple, and works just like I want it :)
精彩评论