簡體   English   中英

lambda轉換為bool而不是推導function-pointer-type

[英]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.

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