2017-02-13 41 views
6

我想做一個簡單的事情:如何在C++中使用lambda作爲模板參數與默認值?

void DoUntil(auto predicate = [] { return false; }); 

顯然,這並不工作 - 我必須使用一個模板參數:

template <typename P> 
void DoUntil(P predicate = [] { return false; }); 

但這種說法並沒有工作,要麼 - 鐺給出了一個錯誤:

error: no matching function for call to …
note: candidate template ignored: couldn't infer template argument 'P'

如果我做調用不帶參數的功能,不知何故編譯器無法從默認參數推斷類型:

int main() { DoUntil(); } 

我不想以任何方式使用std::function<>

有沒有其他可能的解決方案來解決我的問題?

+1

這是一個未推演的上下文。從[cppreference](http://en.cppreference。com/w/cpp/language/template_argument_deduction)非推導上下文,一個模板參數,用於函數參數的參數類型中,該函數參數的默認參數正在調用中進行參數推導。 – felix

+0

爲什麼你不想使用'std :: function'? –

回答

6

使用函數重載而不是默認參數功能。創建非模板功能不帶任何參數,除了模板函數:

void DoUntil() ; 

template <typename P> 
void DoUntil(P predicate) ; 

的無參數的版本可以簡單地調用模板版本你想要作爲默認謂語使用拉姆達:

void DoUntil() { DoUntil([] { return false; }); } 

與原有方法的問題是,你試圖通過指定一個默認參數VALU提供一個默認的模板專業化 e,但沒有指定默認模板類型。即使沒有涉及lambda表達式,下面就不行,因爲T沒有默認的類型,即使t有一個默認值:

template <typename T> 
void Foo(T t = 3); 

只需要什麼是指定一個默認類型使用<typename T = int>T的。

正如WhiZTiM的回答中所指出的那樣,涉及λ函數的情況的默認類型必須使用decltype推導出來。這當然是因爲lambda具有隻有編譯器才知道的獨特類型。

3

lambda是一個沒有默認構造函數的匿名類型(因爲如果可用,可以使用它的複製/移動構造函數)。如果你必須去的拉姆達的方式,你可以這樣做:

namespace detail{ auto predicate = [] { return false; }; } 

template <typename P = decltype(detail::predicate)> 
void DoUntil(P pred = detail::predicate); 

而不是試圖擺弄lambda表達式。你可以去好老辦法:

namespace detail{ 
    struct DefaultPredicate{ bool operator()() const { return false; } }; 
} 

template <typename P = detail::DefaultPredicate> 
void DoUntil(P predicate = P{}); 

或者更好的凱爾東街answered

+0

如果您打算在名稱空間範圍內放入一個lambda,請將其設置爲「const」,以使其變爲隱式靜態。 – ildjarn

+0

啊,我想知道如果提供默認參數將工作,如果模板參數是正確的默認。優秀。 –