簡體   English   中英

如果模板沒有可變參數,則將Lambda推導為std :: function

[英]Lambda is deduced to std::function if template has no variadic arguments

template<typename ReturnT, typename... ParamT>
void foo(std::function<ReturnT(ParamT...)> callback)
{}

template<typename ReturnT, typename ParamT>
void bar(std::function<ReturnT(ParamT)> callback)
{}

main()
{    
    foo<int, int>([](int x){ return x; });  // no instance of function 
                                            //   template matches argument list
    bar<int, int>([](int x){ return x; });  // OK
}

foobar之間的唯一區別是foo具有可變參數。 不知何故,編譯器能夠將lambda轉換為bar中的std :: function。

據我所知,模板類型推導不考慮類型轉換。 那么兩個都不應該失敗嗎?

您沒有對bar的類型參數進行任何扣除,它們是完全指定的。

你仍然可以在foo推斷包的尾部,並且因為lambda不是std::function而失敗。

template<typename ReturnT, typename... ParamT>
void foo(std::function<ReturnT(ParamT...)> callback)
{}

現在, foo<int,int>foo<ReturnT=int, ParamsT starts with {int}>

它沒有完全指定ParamT 實際上,沒有辦法完全指定ParamT

作為未完全指定的模板,演繹發生並失敗。 它不會嘗試“如果我只是假設包裝不再進一步”。

你可以解決這個問題:

template<typename ReturnT, typename... ParamT>
void foo(block_deduction<std::function<ReturnT(ParamT...)>> callback)
{}

其中block_deduction看起來像:

template<class T>
struct block_deduction_helper { using type=T; }:
template<class T>
using block_deduction = typename block_deduction_helper<T>::type;

現在扣除在foo的第一個參數上被阻止了。

你的代碼有效。

當然,如果你傳入一個std::function ,它將不再自動推斷出參數。

請注意,推斷類型擦除類型的類型如std::function通常是代碼味道。

將兩者替換為:

template<class F>
void bar(F callback)
{}

如果你必須獲得參數,請使用函數特性助手(SO上有很多)。 如果你只需要返回值,那么std特性已經可以解決了。


您可以這樣做:

tempate<class R, class...Args>
void bar( std::function<R(Args...)> f ) {}
template<class F>
void bar( F f ) {
  std::function std_f = std::move(f);
  bar(std_f);
}

使用演繹指南功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM