2015-02-10 250 views
0

我需要定義一個函數,它以集合和函數作爲輸入來執行集合的漂亮打印。對於這個問題,我想明確地指定函數類型,這樣編譯器會遞歸匹配,因此簽名C++ lambda表達式作爲函數模板中的參數

template<typename T, PrettyPrinter> 
std::string to_string(const std::set<T>& set, PrettyPrinter printer); 

不夠精確,因爲編譯器不能推斷需要一個函數對象的類型。所以相反,我想使用明確的打字

template<typename T> 
std::string PrettyPrinting::to_string(const std::set<T>& set, std::function<std::string(const T&)> printer){ 
    const char* separator = ", "; 
    const char* leftDelimiter = "{"; 
    const char* rightDelimiter = "}" 

    std::string output = leftDelimiter; 
    if(set.begin() == set.end()) return output + rightDelimiter; 

    typename std::set<T>::const_iterator it = set.begin(); 
    output += printer(*it); 
    for(++it; it != set.end(); it++) output.append(separator) += printer(*it); 

    return output + rightDelimiter; 
} 

這就是我所期望的。但是,我不能使用蘭巴表達的另一個模板施工

std::string to_string(const std::set<std::string>& set){ 
    return to_string(set, [](const std::string& input){ return input; }); 
} 

我得到一些奇怪的錯誤lambda函數是不恰當的說法。在另一方面,下面的代碼工作

inline std::string to_string(const std::set<std::string>& set){ 
    std::function<std::string(const std::string&)> printer = [](const std::string& input){ return input; }; 
    return to_string(set, printer); 
} 

是否有任何合理的理由,爲什麼編譯器需要一個明確的函數對象?我應該指定哪種類型,以便可以直接將lambda表達式作爲函數參數來編寫?

+0

[嘗試爲MFC的CMap編寫\ _each算法](http://stackoverflow.com/questions/28437404/trying-to-write-a-for-each-algorithm-for-mfcs- cmap) – Pradhan 2015-02-10 20:17:45

+0

你試過'return to_string (...)' - 即繞過模板參數扣除?這比你的解決方法短得多。 – MSalters 2015-02-11 08:36:47

回答

1

Lambdas和std::function<...>是兩種不同的類型。 不關心隱式轉換。試試這個:

template<typename T, typename PrintLambda, typename = std::enable_if_t<std::is_convertible<PrintLambda, std::function<std::string(const T&)> >::value >> 
std::string PrettyPrinting::to_string(const std::set<T>& set, PrintLambda printer); 

以上確保PrintLambda通過檢查正確的簽名,如果它可以轉換爲相應的std::function

+0

公平。如果編譯器只給出了上面指定的兩個模板定義,那麼對於'set >'類型'自動實例化'to_string'就足夠了。這是顯式鍵入函數對象的最初原因。此外,我的解決方案之間的區別是什麼,如果我賦值爲靜態的(因此ir只會在函數的第一次調用中初始化),lambda被分配給函數對象? – 2015-02-10 21:14:08

+0

@SvenLaur如果你的問題是,在定義了這個模板函數的主體之後,下面的代碼將工作:std :: string to_string(const std :: set &set){ return to_string(set,[](const std :: string&input){return input;}); ',那麼是的,它會。 – Pradhan 2015-02-10 21:26:18

相關問題