簡體   English   中英

如何使用 lambda 在 std::function 參數中推導出模板類型?

[英]How to have template type deduced in std::function arguments with lambda?

我有一個 boost::variant 並且我只想在變體是特殊類型時才執行函子,所以我編寫了這個函數:

template<typename T, typename Variant>
void if_init(Variant& opt_variant, std::function<void(T)> functor){
    if(auto* ptr = boost::get<T>(&opt_variant)){
        functor(*ptr);
    }   
}

這很好用,但我希望推導出類型 T,以便我可以這樣寫:

if_init(b, [](double var){ std::cout << "I'm double and set" << std::endl; });

但是沒有推斷出類型:

type_inference.cpp:19:5: error: no matching function for call to 'if_init'
    if_init(b, [](double var){ std::cout << "I'm double and set" << std::endl; }); 
    ^~~~~~~
type_inference.cpp:10:6: note: candidate template ignored: failed template argument deduction
    void if_init(Variant& opt_variant, std::function<void(T)> functor){

如果我寫:

if_init<double>(b, [](double var){ std::cout << "I'm double and set" << std::endl; });

它運作良好。

有沒有辦法推導出類型 T ? 我只想輸入 T 一次。 這里的類型很短,但在實際情況下,有長類型。

我正在使用 CLang 3.2。

這是完整的測試用例(第一個調用編譯不是第二個):

#include <iostream>
#include <functional>
#include <boost/variant.hpp>

typedef boost::variant<int, double> Test;

template<typename T, typename Variant>
void if_init(Variant& opt_variant, std::function<void(T)> functor){
    if(auto* ptr = boost::get<T>(&opt_variant)){
        functor(*ptr);
    }   
}

int main(){
    Test b = 1.44; 

    if_init<double>(b, [](double var){ std::cout << "I'm double and set" << std::endl; });
    if_init(b, [](int var){ std::cout << "I'm int and set" << std::endl; });      

    return 0;
}

我建議您將std::function<Sig>視為符合Sig作為簽名的任何一個函子的容器 - 並且可以隨時替換。 這個功能對例如std::vector<std::function<Sig>>非常方便,因為這樣的容器可以容納不同類型的函子。

在您的情況下,因為您只關心一個函子,所以您真的不需要std::function<Sig>的功能。 因此,我建議您像這樣聲明您的函數模板:

template<typename T, typename Variant, typename Functor>
void if_init(Variant& opt_variant, Functor functor);

如果您擔心這不能說明Functor必須符合void(T)簽名,請注意std::function<Sig>也不強制執行此操作:盡管顯然您最終遇到編譯錯誤,但它不是一個很好的。 計划進行更改(也許您的實現也有),但更改為另一種錯誤。 對您的情況仍然沒有幫助。

我個人使用模板別名( 在模板參數列表中)來記錄和強制執行函子應符合的內容。 這最終看起來像:

// Documents that e.g. long l = std::forward<Functor>(functor)(42.)
// should be a valid expression -- a functor that returns int would
// also be accepted.
// Triggers a hard-error (typically a static_assert with a nice message)
// on violation.
template<typename Functor, Requires<is_callable<Functor, long(double)>>...>
R foo(Functor functor);

// Documents that this function template only participates in overload resolution
// if the functor conforms to the signature.
// Does not trigger a hard-error (necessary by design); if everything goes right
// then another overload should be picked up -- otherwise an error of the kind
// 'no matching overload found' is produced
template<typename Functor, EnableIf<is_callable<Functor, long(double)>>...>
R bar(Functor functor);

至於您的確切問題,C++ 的規則不允許在您的情況下推導出模板參數。 這真的不是一個容易解決的“問題”,如果它是一個。 您可以找到有關此的更多信息

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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