2013-10-30 141 views
4
#include <functional> 

using namespace std; 

template<class CharType> 
void f1(CharType* str, function<bool(CharType)> fn_filter) 
{} 

template<class CharType> 
void f2(CharType* str, function<bool(char)> fn_filter) 
{} 

void f3(char* str, char c) 
{ 
    auto fn_filter = [=](char e) -> bool 
    { 
     return e == c; 
    }; 

    f1(str, fn_filter); // error C2784 
    f2(str, fn_filter); // OK 
} 

int main() 
{ 
    f3("ok", 'k'); 
} 

// error C2784: 'void f1(CharType *,std::function<bool(CharType)>)' 
// : could not deduce template argument for 'std::function<bool(CharType)>' 
// from 'f2::<lambda_36be5ecc63077ff97cf3d16d1d5001cb>' 

我的編譯器是VC++ 2013爲什麼std :: function不能接受推導類型作爲其模板參數?

爲什麼f1不會達到預期效果?

+2

我知道這個問題的答案,但我不能我想不出一個好的方法來說出它。如果沒有人嘗試,我會稍後再做。 –

回答

4

編譯器的問題是要決定哪些參數用於類型推導。如果從第二個參數和它使用的第一個打破的可能扣除幫助編譯,它按預期工作:

template<typename T> struct identity { using type = T; }; 

template<class CharType> 
void f1(CharType* str, typename identity<function<bool(CharType)>>::type fn_filter) 
{} 

Live example

+0

好的解決方案! (或者很好的解決方法);) – xmllmx

8

該lambda沒有類型std::function<bool(char)>,它只是一些可執行定義類型的可調用對象。

它可以是轉換成std::function<bool(char)>,但這並不能幫助編譯器推導模板大小寫的類型。例如,可能有很多CharType的可能性,其中lambda可以轉換爲std::function<bool(CharType)>

編譯器試圖將lambda的類型與模板函數的參數進行匹配。 lambda具有例如類型lambda_t_1234和模板參數是std::function<bool(CharType)>。這些類型是不相關的,並不清楚CharType應該在這裏。

這對lambda或std::function<>也不是特別的。同樣的情況在所有這些情況下:

template<typename Char> 
void f(const std::basic_string<Char> &str) { 
} 

如果你試圖調用一個char*參數,它不會工作,這個模板函數,因爲模板參數的連接是不明確的。

+1

你的例子雖然略有不同,但由於OP作爲* explicit *'CharType *'作爲第一個參數並且傳遞了一個'char *',因此我們可以合理地期望'在'OP中'CharType'被推斷爲'char'非常特殊的情況。 –

+0

@ MSalters:不,他不是。對於第二個參數也推導出「CharType」,它不是不可推論的上下文。嘗試傳遞任何'std :: function ',其中'T'!='char'。你會得到一個扣除不匹配。但是,您可以將其作爲不可推卸的背景,並以此方式強制轉換。 – Xeo

+0

@Xeo:對。你確實有兩個可推論的背景,在一個背景下推演失敗。不過SFINAE並不是這樣,所以這種失敗是致命的。 – MSalters

相關問題