2017-01-20 23 views
0

編譯器如何解釋符號_1,以及如何結合發生的呢? 請看下面的例子:在回調中佔位符如何作用_1?

class A { 
public: 
    boost::function<void (int x)> g; 
}; 

class B { 
public: 
    B() {} 
    static void foo(int i) { cout << "Hack: " << i <<endl; } 
}; 

int main() { 
    A a; 
    a.g = boost::bind(B::foo,_1); 
    a.g(2); 
    return 0; 
} 

什麼魔法行boost::bind(B::foo,_1);內部發生了什麼?

怎麼_1被馬培德到下一行a.g(2);傳遞的參數?

輸出:
哈克:2

+0

參見在其上的標準文檔http://en.cppreference.com/w/cpp/utility/functional/placeholders因爲它們加入C++ 11。基本上他們只是特定的類型和價值,「綁定」知道如何解釋。 – clcto

+0

編譯器將'_1'解釋爲名稱,與解釋'x'相同。該名稱的實現位於boost庫中,該庫是開源的,因此您可以自行檢查它。 –

+0

但你能解釋其中'_1'被映射到'A.G(2)傳遞的參數完整的機制;' – Rama

回答

0

我會解釋給我最大的能力。首先,_1不過是一個全局變量。在這方面沒有什麼特別的,它也可以命名爲其他任何東西 - placeholder1SergeyA。然而,像_1名短,具有很好理解的含義,並與_,從而降低它與程序中的其它全球衝突的名字可能性開始。

神奇的是在該變量的類型。它有一個特殊的類型,它反映在生成的bind*對象中。之後,當調用operator()時,該類型被認爲是從operator()參數中獲取參數。

下面是一些說明C++ - 像僞代碼,這是不正確的,但說明:

template<class F, class... ARG> 
struct bound { 
    bound(F f, ARGS&&... args) : bound_args(args...), functor(f) { } 
    std::tuple<ARG...> bound_args; 
    template<class... T> 
    void operator()(T&&... args); 

    F f; 
}; 

template<class F, class... T> 
auto bind(F f, T&& args) { 
    return bound<std::remove_reference_t<T>...>(f, args...); 
} 

現在,讓我們引入一個佔位符類型。

template<size_t N> 
struct placeholder { 
    enum { position = N; }; 
    template<class...T> 
    auto operator()(T&&... args) { 
     return std::get<position>(std::make_tuple(arg...)); 
    } 
}; 

placeholder<0> _1; 
placeholder<1> _2; 

到目前爲止這麼好。現在,讓我們看看運營商()的實際工作原理綁定的對象上:這裏

template<class... BOUND_ARGS> 
template<class... CALL_ARGS> 
void bound_object<BOUND_ARGS...>::operator() (CALL_ARGS&&... args) { 
    call_impl(args..., make_index_sequence<sizeof...(BOUND_ARGS)>{}); 
} 

make_index_sequence是需要的元組值提取到函數的參數,所以不要太在意它。這裏是call_impl;

template<class... BOUND_ARGS> 
template<class... CALL_ARGS, size_t... ix> 
void bound_object<BOUND_ARGS...>::call_impl(CALL_ARGS&&... args, std::index_sequence<ix...>) { 
    f(to_arg().(std::get<ix>(bound_args), args...)...); 
} 

而且拼圖的最後一塊是to_arg

template<class B, class... ARGS> 
auto to_arg(B&& b, ARGS... args) { 
    return b; 
} 

template<class... ARGS> 
auto to_arg(placeholder<0> p, ARGS&&... args) { 
    return p(args); 
} 

template<class... ARGS> 
auto to_arg(placeholder<1> p, ARGS&&... args) { 
    return p(args); 
} 

to_arg這裏全是給你要麼綁定參數或所提供的一個參數的基礎上,結合參數類型。在我上面的例子中,我使用了3個重載,因爲你可以部分地專門化一個函數,但是當然,把它放在一個類中並部分地專門化這個類會更有意義。

+0

哇!非常感謝!現在我需要閱讀**反射**,**元組**和'make_index_sequence' – Rama

+0

反射在這裏不相關,但元組是。 – SergeyA