[英]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';
}
您有兩個不同的問題:
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
:
auto f() { return /* stuff */; }
auto f() { return /* stuff */; }
使用auto
規則,從未演繹引用類型。 這實際上通常是你想要的 - 你真的不想意外地返回已經死亡的東西的引用 - 這確實是你的g()
如果它返回一個引用會做的! 要獲得“完美返回”,請使用decltype(auto)
。
請參閱cppreference上的typeid運算符 :
typeid( type )
- 表示表示類型type
的std::type_info
對象。 如果type
是引用類型,則結果引用引用的類型。
換句話說,typeid()將丟棄/忽略任何頂級引用限定符。
為了避免這種情況,你可以將你的類型包裝成某種東西,比如像void(your_type)
這樣的函數簽名,它會給你A&&
的預期結果
我可以看到,當使用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.