2017-05-03 132 views
61

我已經使用std::tie沒有太多考慮。它的工作原理,所以我剛剛接受了:std :: tie如何工作?

auto test() 
{ 
    int a, b; 
    std::tie(a, b) = std::make_tuple(2, 3); 
    // a is now 2, b is now 3 
    return a + b; // 5 
} 

但如何做到這一點黑魔法工作? std::tie更改ab如何創建一個臨時?我覺得這更有趣,因爲它是一個圖書館功能,而不是語言功能,所以它肯定是我們可以實現自己並理解的東西。

回答

94

爲了闡明核心概念,我們將其簡化爲一個更基本的例子。雖然std::tie是返回(元組)更值的函數是有用的,我們可以把它理解僅僅只用一個價值罰款:

int a; 
std::tie(a) = std::make_tuple(24); 
return a; // 24 

的事情,我們需要知道以前進:

  • std::tie構造並返回一個引用元組。
  • std::tuple<int>std::tuple<int&>是兩個完全不同的類,它們之間沒有任何關聯,除此之外它們是從同一個模板生成的,std::tuple
  • 元組具有operator=接受不同類型的(但相同數量),其中,每個成員被分配可單獨從cppreference的元組:

    template< class... UTypes > 
    tuple& operator=(const tuple<UTypes...>& other); 
    

    (3)對於所有的i,分配std::get<i>(other)std::get<i>(*this)

下一步是擺脫這些功能只有在你的方式,所以我們可以改變我們的代碼是:

int a; 
std::tuple<int&>{a} = std::tuple<int>{24}; 
return a; // 24 

下一步是看到什麼發生在這些結構內部。 對於這一點,我創建了2種T取代了std::tuple<int>Tr取代std::tuple<int&>,精簡到最低限度,爲我們的操作:

struct T { // substituent for std::tuple<int> 
    int x; 
}; 

struct Tr { // substituent for std::tuple<int&> 
    int& xr; 

    auto operator=(const T& other) 
    { 
     // std::get<I>(*this) = std::get<I>(other); 
     xr = other.x; 
    } 
}; 

auto foo() 
{ 
    int a; 
    Tr{a} = T{24}; 

    return a; // 24 
} 

最後,我想擺脫的結構都在一起(當然,這不是相當於100%,但對我們來說足夠接近,並明確足以讓它):

auto foo() 
{ 
    int a; 

    { // block substituent for temporary variables 

    // Tr{a} 
    int& tr_xr = a; 

    // T{24} 
    int t_x = 24; 

    // = (asignement) 
    tr_xr = t_x; 
    } 

    return a; // 24 
} 

所以基本上,std::tie(a)初始化數據成員參考astd::tuple<int>(24)創建一個值爲24的數據成員,並且該分配將24分配給第一個結構中的數據成員引用。但由於該數據成員是綁定到a的參考,所以基本上將24分配給a

13

這不會以任何方式回答你的問題,但是讓我發佈它,因爲C++ 17基本上已經準備就緒(支持編譯器),所以在想知道過時的東西是如何工作的時候,可能值得看看如何C++的當前版本和未來版本也適用。

使用C++ 17,您幾乎可以從頭開始std::tie轉而使用所謂的結構化綁定。他們也是這樣做的(好吧,不一樣,但它們有相同的淨效果),儘管你需要輸入更少的字符,它不需要庫支持,而且你還有也有有能力引用if這恰好是你想要的。

(請注意,在C++ 17層的構造做參數推導,所以make_tuple變得有點畫蛇添足了。)

int a, b; 
std::tie(a, b) = std::make_tuple(2, 3); 

// C++17 
auto [c, d] = std::make_tuple(4, 5); 
auto [e, f] = std::tuple(6, 7); 
std::tuple t(8,9); auto& [g, h] = t; // not possible with std::tie 
+2

如果最後一行編譯我有點擔心。它看起來像綁定一個非法的臨時參考。 –

+0

@NirFriedman在這種情況下你不會獲得終生延期嗎? – Neil

+2

@Neil它必須是右值引用或常量左值引用。您不能將左值引用綁定到prvalue(臨時)。儘管這已經是MSVC多年的「延伸」了。 –

相關問題