簡體   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