雖然有很多東西在那裏浮出來關於獲取任何模板化回調函數/方法(當然包括lambda當然)的返回類型,但我很難找到信息關於解析lambda函數的完整調用簽名。至少在gcc 4.7中,這似乎是一個正常竅門(見下文)不起作用的邊緣情況。這裏就是我想要做的,到目前爲止(當然是一個精簡版)...使用可變參數模板參數來解析lambda簽名
template<typename Sig>
struct invokable_type { };
template<typename R, typename...As>
struct invokable_type<R(As...)> {
static constexpr size_t n = sizeof...(As);
typedef R(callable_type)(As...);
template<size_t i>
struct arg {
typedef typename peel_type<i, As...> type;
};
};
peel_type<size_t, typename...>
是不是在這裏爲簡便起見包括在內,但它是一個簡單的參數類型削皮器(我覺得有一個建在C + + 11,但我從來沒有打擾看)。這個問題並不重要。
然後,當然,特(和進一步的性質/類型定義),用於可調用類型如R(*)(As...)
,R(&)(As...)
,(R(T::*)(As...)
,std::function<R(As...)>
,方法CV限定符,方法左值/右值限定符,等,等,等無數存在
然後,某處在路上,我們有一個可愛的函數或方法(這裏的功能,無所謂),看起來像......
template<typename C, typename...As>
static void do_something(C&& callback, As&&...as) {
do_something_handler<invokable_type<C>::n, As...>::something(std::forward<C>(callback), std::forward<As>(as)...);
}
別說什麼do_something_handler
呢?這完全無關緊要。問題在於lambda函數。
對於我專門爲其設計的所有可能的通用可調用簽名(它看起來都是非STL仿函數),當do_something()
作爲第一個參數(模板演繹完全有效)被調用時,它會很好地工作。但是,lambda函數會導致未捕獲的類型簽名,導致使用invokable_type<Sig>
,這意味着像::n
和::args<0>::type
這樣的東西根本不存在。
不-A-問題例如...
void something(int x, int y) {
return x * y;
}
......後來......
do_something(something, 7, 23);
問題例如...
do_something([](int x, int y) {
return x * y;
}, 7, 23);
如果我沒有理解lambda函數正確,編譯器可能將此lambda編譯爲靜態函數定義範圍的「命名空間」(gcc當然似乎)。對於我的生活,我無法弄清楚簽名實際上是什麼。它看起來確實有一個應該通過模板專業化(基於錯誤報告)來推理。
另一個問題是即使有我可以使用的簽名,交叉編譯器如何危險? lambda編譯簽名是標準化還是全面?
lambda表達式的類型是帶有函數調用操作符的類類型(閉包類型)。不過,我不確定'typedef R(invokable_type)(As ...)'是什麼。 – dyp
@DyP:lambda表達式*不是*明確的類類型。在C++ 11規範中沒有這樣的要求,如果沒有捕獲完成,肯定不需要。請指出規範,如果你知道這是事實,我立場糾正(並有一些工作,這是很好:)。至於typedef,它是該函數簽名的裸typedef。它不是一個指針或ref函數,或者它們分別是'typedef R(* invokable_type)(As ...)'和'typedef R(&invokable_type)(As ...)'。就像我說的那樣,我專門爲這一切做了準備。 –
[expr.prim.lambda]/3「* lambda表達式*(也是閉包對象的類型)的類型是唯一的,未命名的非聯合類類型 - 稱爲*閉包類型*」 – dyp