[英]lambda converted to bool instead of deducing function-pointer-type
我想為operator<<
實現一個重載,該重載允許我調用給定的函數並輸出結果。 因此,我寫了一個重載,但是選擇了向bool的轉換,並且當我自己編寫一個函數時,它將無法編譯。
編輯:知道我不想調用lambda,而是將其傳遞給應使用默認構造的參數列表進行調用的函數。
我已經添加了我的代碼:
#include <iostream>
template<typename T>
void test(T *) {
std::cout << "ptr" << std::endl;
}
template<typename T>
void test(bool) {
std::cout << "bool" << std::endl;
}
template<typename Ret, typename ...Args>
void test(Ret(*el)(Args...)) {
std::cout << "function ptr\n" << el(Args()...) << std::endl;
}
template<typename Char_T, typename Char_Traits, typename Ret, typename ...Args>
std::basic_ostream<Char_T, Char_Traits>& operator<<(
std::basic_ostream<Char_T, Char_Traits> &str, Ret(*el)(Args...)) {
return str << el(Args()...);
}
int main() {
std::boolalpha(std::cout);
std::cout << []{return 5;} << std::endl; // true is outputted
test([]{return 5;}); // will not compile
}
我將gcc 7.3.1與版本標志-std=c++14
。
編輯:錯誤消息:
main.cc: In function ‘int main()’:
main.cc:25:23: error: no matching function for call to ‘test(main()::<lambda()>)’
test([]{return 5;});
^
main.cc:5:6: note: candidate: template<class T> void test(T*)
void test(T *) {
^~~~
main.cc:5:6: note: template argument deduction/substitution failed:
main.cc:25:23: note: mismatched types ‘T*’ and ‘main()::<lambda()>’
test([]{return 5;});
^
main.cc:9:6: note: candidate: template<class T> void test(bool)
void test(bool) {
^~~~
main.cc:9:6: note: template argument deduction/substitution failed:
main.cc:25:23: note: couldn't deduce template parameter ‘T’
test([]{return 5;});
^
main.cc:13:6: note: candidate: template<class Ret, class ... Args> void test(Ret (*)(Args ...))
void test(Ret(*el)(Args...)) {
^~~~
main.cc:13:6: note: template argument deduction/substitution failed:
main.cc:25:23: note: mismatched types ‘Ret (*)(Args ...)’ and ‘main()::<lambda()>’
test([]{return 5;});
您的問題是模板參數推導僅對傳遞給test
的實際參數進行。 並非所有可能將參數轉換為可能的類型都進行了轉換。 那可能是一個無限的集合,所以顯然是不行的。
因此,模板參數推導是在實際的lambda對象上完成的,該對象具有無法說明的類類型。 因此,由於lambda對象不是指針,因此對test(T*)
的推論失敗。 顯然,不能從test(bool)
推導出T
最后,推導對於test(Ret(*el)(Args...))
失敗,因為lambda對象也不是函數的指針。
有一些選擇。 您甚至可能不需要模板,可以接受std::function<void(void)>
並依靠它具有模板化構造函數的事實。 或者,您可以只接受一個test(T t)
參數並將其稱為t()
。 T
現在將推斷出實際的lambda類型。 最合適的解決方案可能是使用std::invoke
並接受模板vararg列表。
template<typename T>
void test(bool) {
std::cout << "bool" << std::endl;
}
不需要模板。 實際上,您重載了函數,而不是模板。 替換為
void test(bool) {
std::cout << "bool" << std::endl;
}
現在,您的示例將編譯。
即使不捕獲的lambda隱式轉換為函數指針,函數模板也必須完全匹配才能成功演繹,但不會執行任何轉換。
因此,最簡單的解決方法是強制使用+
int main() {
std::boolalpha(std::cout);
std::cout << []{return 5;} << std::endl; // true is outputted
test(+[]{return 5;});
// ^
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.