簡體   English   中英

使用`std :: move`自動返回類型推導

[英]auto return type deduction with `std::move`

以下程序的輸出都是1A ,當通過c++filt -t時是A 我可以看到,當使用std::move返回時,返回類型被推導為值類型而不是rvalue引用類型。 對於大多數使用std::move返回的用例來說,這是有道理的,但是這是什么原因? std::move返回一個右值引用,但為什么返回類型會自動推斷為值類型?

#include <iostream>
#include <memory>
#include <utility>
#include <typeinfo>

struct A
: std::unique_ptr<int>
{
    auto f()
    {
        return A();
    }

    auto g()
    {
        return std::move(A());
    }
};

int main()
{
    std::cout << typeid(decltype(A().f())).name() << ' ';
    std::cout << typeid(decltype(A().g())).name() << ' ';
    std::cout << typeid(A).name() << '\n';
}

您有兩個不同的問題:

  1. 用於檢查返回類型的工具不適合用途。 typeid strip referenceness然后是top-level cv-qualification; typeid(int)typeid(const int)typeid(const int&&)是一回事。 要測試實際類型,請使用std::is_same ; Boost.TypeIndex具有type_id_with_cvr 還有你做template<class T> class TD;的技巧template<class T> class TD; ,嘗試定義TD</*type to be checked*/>的類型為TD</*type to be checked*/>的變量TD</*type to be checked*/> ,並從編譯器生成的錯誤消息中讀出類型。

但這在這里是無害的; f()g()確實按值返回A

  1. auto f() { return /* stuff */; } auto f() { return /* stuff */; }使用auto規則,從未演繹引用類型。 這實際上通常是你想要的 - 你真的不想意外地返回已經死亡的東西的引用 - 這確實是你的g()如果它返回一個引用會做的!

要獲得“完美返回”,請使用decltype(auto)

請參閱cppreference上的typeid運算符

typeid( type ) - 表示表示類型typestd::type_info對象。 如果type是引用類型,則結果引用引用的類型。

換句話說,typeid()將丟棄/忽略任何頂級引用限定符。

為了避免這種情況,你可以將你的類型包裝成某種東西,比如像void(your_type)這樣的函數簽名,它會給你A&&的預期結果

示例: http//coliru.stacked-crooked.com/a/d6af3eff8216246f

我可以看到,當使用std :: move返回時,返回類型被推導為值類型而不是rvalue引用類型。 對於大多數使用std :: move返回的用例來說,這是有道理的,但是這是什么原因? std :: move返回一個右值引用,但為什么返回類型會自動推斷為值類型?

普通auto類型推導與普通模板參數推導相同(除了std::initializer_list情況)。 換句話說,除非使用通用引用&& ,否則auto永遠不會推斷引用。

decltype(auto) ,另一方面,執行類似類型的扣除auto ,但也增加了額外的decltype扣除規則,即允許L值和R值引用的推斷。 如果您希望將其作為參考推斷,那么您可能希望將其用於返回類型。

typeid(expression)查詢有關靜態 expression 對於任何引用,包括stval std::move()返回的rvalue引用,這意味着查詢引用所引用的對象的類型,而不是引用本身的類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM