2017-10-09 52 views
0

鑑於lambda表達式具有以下結構:過載模板拉姆達不知道的參數類型用於非模板化參數

auto lambda_1 = [](int x, auto p) -> void {...}; 
auto lambda_2 = [](float x, auto p) -> int {...}; 

我想提取的x類型,以及返回類型,給定一個已知類型p

返回類型是相當簡單的,只要x是默認constructible(我可以做一個需求沒有問題):

template<typename CB_T> 
void foo(CB_T cb) { 
    using res_type = decltype(cb({}, std::declval<KnownP>())); 
} 

同樣,如果第二個參數沒有infered,我可以很容易使用類似function_traits的東西找到第一個參數的類型。

我知道我可以按照我想要的方式觸發重載分辨率,如我在不知道x的類型是什麼類型的情況下提取結果類型的證據,所以我沒有看到爲什麼我不應該拉這個關閉。

感覺就像我有拼圖的每一塊,但我似乎無法計算出如何獲取該場景中的重載函數的類型,以便提取x的類型。

有什麼建議嗎?

+0

你試圖解決的實際問題是什麼?一般來說,這是不可能的,沒有反思。對於沒有SFINAE shenanig的'[](T,auto)'形式的*特別* lambdas,這是可能的,但是這看起來很奇怪。 – Barry

+0

@Barry它是... ...錯綜複雜的...我需要這個爲了分配一個臨時緩衝區來傳遞一個模板子進程的引用,以便在調用lambda之前進行填充。我需要第二個參數是模板化的,因爲實際類型會非常不透明,我真的不想強加給用戶(我也希望lambda可以用不同的不透明類型重用)。 [參考](https://github.com/FrancoisChabot/abulafia/issues/15) – Frank

+0

@Barry我真的希望能夠接受任意的函數而不是隻是lambda,但要求用戶在lambdas中包裝函子是可以接受的必要。 (雖然我真的想支持閉包) – Frank

回答

1

在你現在處理的lambda表達式的具體情況:

  • 取兩個參數:第一個是一個非模板,其中第二個是一個模板
  • 有返回類型適用於所有模板參數(例如沒有enable_if等)

然後你可以使用一個假推定器類型的第一個參數:

struct arbitrary { template <class T> operator T(); }; 
using res = decltype(cb(arbitrary{}, std::declval<KnownP>())); 

或者您可以使用function_traits來查找我們將要使用的特定operator()

using oper = decltype(&CB_T::template operator()<KnownP>); 
using arg0 = typename function_traits<oper>::template arg<0>::type; 
using res = decltype(cb(std::declval<arg0>(), std::declval<KnownP>()); 

兩者都是真的具體到這個特殊的拉姆達佈局雖然。

+0

'decltype(&CB_T :: template operator())'Doy!爲什麼我沒有想到這個?這正是我所期待的。我馬上試一試。 – Frank

+0

是否有一個特別的理由使用'任意{}'而不是'{}'? – Frank

+0

只要結構是特定的。我實際上想要允許2-3個不同的參數配置,但是我應該能夠使用'std :: is_invocable'對它進行排序 – Frank