繁体   English   中英

是否有可能故意破坏特定类型的保证复制省略?

[英]Is it possible to intentionally defeat guaranteed copy elision for a particular type?

在 C++17 及更高版本中,保证复制省略意味着可以通过一系列函数返回不可移动对象,一直到最终调用者:

struct NonMoveable {
  NonMoveable() = default;
  NonMoveable(NonMoveable&&) = delete;
};

NonMoveable Foo() { return NonMoveable(); }
NonMoveable Bar() { return Foo(); }
NonMoveable Baz() { return Bar(); }

NonMoveable non_moveable = Baz();

是否有一些技巧可以禁用特定类型的保证复制省略,这样就不可能编写像上面的BarBaz这样的函数来传递从另一个函数获得的NonMoveable对象? (我不知道Foo是否应该被禁止。)


我知道这是一个奇怪的要求。 如果您对我正在尝试做的事情感兴趣:我正在开发一个协程库,其中的约定是,如果您从一个函数返回一个Task ,那么该函数的所有引用参数都需要保持有效,直到任务准备就绪,即直到任务的co_await表达式求值。 如果从另一个协程调用协程,这一切都很好,因为我已将Task类型安排为不可移动并按值接受:除了立即co_await它和任何临时变量之外,您不能对它做任何事情您在对子协程的调用中提供的内容将一直存在,直到co_await表达式计算为止。

除了你可以用Task做一件事:编写上面的BarBaz之类的函数,它们确实return Foo()而不是co_return co_await Foo() 如果涉及到Foo的参数,它可能是临时的,在这种情况下co_return co_await Foo(...)但不return Foo(...)是安全的。

这可能会变得非常微妙。 例如,一个std::function<Task(SomeObj)>内部包含一个return语句,并且会愉快地绑定到一个接受const SomeObj&的 lambda。 当它被调用时,它将为 lambda 提供对其按值参数的引用,该参数在 lambda 挂起时被销毁。

我正在寻找一种更优雅的方法来防止这个问题,但同时我想让有问题的表单无法编译(这也有助于识别用户代码中的问题集)。 我希望这是不可能的,但也许有一些我没有想到的技巧。

您不能禁用保证省略。 它是 C++17 及更高版本中纯右值概念的属性 这不是任何类型都可以影响的。

此外,即使你可以,这也不会得到你想要的效果。 prvalue 仍可用于直接初始化命名变量。 一旦发生这种情况,构造函数调用中使用的任何临时对象(用于const&&&参数)都将结束其生命周期。 如果给构造函数提供了任何引用参数,它们可能不再存在。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM