2016-02-28 42 views
9

我已經閱讀了許多關於variadic模板和std :: bind的文章,但我想我仍然不理解它們是如何一起工作的。我認爲當涉及到使用可變參數模板時,我的概念有點模糊,使用了什麼std :: bind以及它們如何結合在一起。關於std :: ref()和std :: bind()與variadic模板有點朦朧

在下面的代碼中,我的lambda對TestClass類型的對象使用了點運算符,但即使當我傳入類型爲std :: ref的對象時,它們仍然可以工作。這究竟是怎麼回事?隱式轉換如何發生?

#include <iostream> 
using std::cout; 
using std::endl; 
#include <functional> 
#include <utility> 
using std::forward; 

class TestClass { 
public: 
    TestClass(const TestClass& other) { 
     this->integer = other.integer; 
     cout << "Copy constructed" << endl; 
    } 
    TestClass() : integer(0) { 
     cout << "Default constructed" << endl; 
    } 
    TestClass(TestClass&& other) { 
     cout << "Move constructed" << endl; 
     this->integer = other.integer; 
    } 

    int integer; 
}; 

template <typename FunctionType, typename ...Args> 
void my_function(FunctionType function, Args&&... args) { 
    cout << "in function" << endl; 
    auto bound_function = std::bind(function, args...); 
    bound_function(); 
} 

int main() { 

    auto my_lambda = [](const auto& one, const auto& two) { 
     cout << one.integer << two.integer << endl; 
    }; 

    TestClass test1; 
    TestClass test2; 
    my_function(my_lambda, std::ref(test1), std::ref(test2)); 

    return 0; 
} 

更具體地說,我通過在與兩個TestClass對象test1test2一個的reference_wrapper的兩個實例,但是當我將它們傳遞到拉姆達的.操作符神奇。我希望你有使用::get()功能中的reference_wrapper,使這項工作,但在調用.integer數據成員的工作..

+0

*「隱式轉換是如何發生的?」 - 隱式轉換什麼類型? – soon

+0

我會更新我的問題,以便更清楚。對不起,關於 – Curious

+0

@soon那裏!這是否使我的問題更清楚? – Curious

回答

5

參考解包是由std::bind()結果執行:

如果參數類型爲std::reference_wrapper<T>(例如,在初始調用bind時使用了std::refstd::cref),則存儲在綁定參數中的引用T&將傳遞給可調用對象。

相應的標準可以在N4140 draft [func.bind.bind]/10中找到。

+0

哇!這太神奇了。你也可以建議一些地方,我可以瞭解更多關於這些std :: bind和variadic模板嗎?因爲目前他們對我來說似乎很神奇,當事情看起來像魔術時,我無法真正編程...... – Curious

+0

@Curious [The Definitive C++ Book Guide and List](http://stackoverflow.com/q/388242/3959454) –

+2

@Curious:值得一提的是,你可能應該單獨研究bind和variadic模板。它們沒有任何不尋常的相互作用,無論是否使用可變參數都可以完全相同,而且可變參數在有或沒有綁定時的作用完全相同。因此,單獨對它們進行研究並不是頭重腳輕。 –

0

重要的是要注意,與std::bind;

bind的參數被複制或移動,並且永遠不會通過引用傳遞除非包裹在std::refstd::cref

的「通過引用傳遞」上面實現,因爲std::ref提供的std::reference_wrapper一個結果是,「包裹」的參考提供的值的類型。

std::reference_wrapper是一個類模板,它將可引用的可指定對象中的引用封裝起來。它經常被用作一種機制來將參考文件存儲在標準容器(如std::vector)中,這些標準容器通常無法保存參考。

舉例來說,bind對參考文獻的解釋是什麼(沒有bind);

#include <iostream> 
#include <utility> 
#include <functional> 

int main() 
{ 
    using namespace std; 
    int a = 1; 
    auto b = std::ref(a); 
    int& c = b; 
    cout << a << " " << b << " " << c << " " << endl; // prints 1 1 1 
    c = 2; 
    cout << a << " " << b << " " << c << " " << endl; // prints 2 2 2 
} 

Demo code