如何从我的专用 std::max 返回临时值?

发布于 2024-09-11 09:17:43 字数 419 浏览 1 评论 0原文

你好! 我想将 std::max 专门用于特定于平台的分数类型。

我想要使​​用的特定于系统的 max 的原型如下所示:

fract builtin_max(fract a, fract b);

我对专门的 std::max 的想法如下所示:

template <> inline
const fract& std::max<fract>(const fract& a, const fract& b) {
    return builtin_max(a, b);
}

然而,编译器会抱怨返回对本地临时对象的引用。有什么办法可以解决这个问题吗?

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 like 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

坚持沉默 2024-09-18 09:17:43

您可以按值返回结果。那么RVO很可能会发生。最终你会得到你想要的行为。

我会将 builtin_max 声明更改为

fract builtin_max(const fract& a, const fract& b);

它将帮助编译器识别 RVO 的可能性。

最后你的 max 看起来像:

template <> 
fract std::max<fract>(const fract& a, const fract& b) {
    return builtin_max(a, b);
}

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);
}
離殇 2024-09-18 09:17:43

如果您可以修改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 函数。所有采用 fract 值的 max 的不合格使用都会在尝试使用 std::maxmax 函数代码>默认模板。话又说回来,这对于对 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
}

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
}
蓝颜夕 2024-09-18 09:17:43

我的解决方案是这样做:

fract std::max(fract a, fract b) {
    return builtin_max(a, b);
}

超级简单,并且就像我想要的那样工作:)

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 :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文