Message我正在嘗試為作為引數的函式創建代理類。
template<typename MsgType>
using SendFunctor = void(*)(MsgType&);
struct Message {};
template<typename T>
struct Test {
Test(T t) {
Message msg;
t(msg);
}
};
template<typename MsgType>
Test(SendFunctor<MsgType>) -> Test<SendFunctor<MsgType>>;
然后我在里面main簡單地宣告一個變數,一切都可以正常使用自由函式和 lambda
Test test([](Message&) { std::cout << "Hello2" << std::endl; });
但是,在添加另一個模板引數Test并修改推導指南后
template<typename MsgType, typename T>
struct Test {
Test(T t) {
Message msg;
t(msg);
}
};
template<typename MsgType>
Test(SendFunctor<MsgType>) -> Test<Message, SendFunctor<MsgType>>;
// or what I really want to achieve
// template<typename MsgType>
// Test(SendFunctor<MsgType>) -> Test<MsgType, SendFunctor<MsgType>>;
我有一個錯誤class template argument deduction failed。事實上,如果我將一個自由函式傳遞給建構式,一切都會正常作業。
有人可以向我解釋一下,為什么這里的 lambda 會破壞整個推論嗎?我該如何解決這個問題?
uj5u.com熱心網友回復:
它在第一種情況下也不起作用,您使用的是默認扣除指南。
當你寫作時
Test test([](Message&) { std::cout << "Hello2" << std::endl; });
它實際上被推斷為
Test<some_lambda_type> test([](Message&) { std::cout << "Hello2" << std::endl; });
你可以寫
Test test( [](Message&){}); // : convert it to function pointer
兩種情況都應該有效。
uj5u.com熱心網友回復:
沒有捕獲的 Lambda 可以隱式轉換為函式指標,因此在這方面其他答案是錯誤的。
問題是編譯器無法從 lambda 的引數型別推斷模板引數。這樣想,如果你傳遞了一個通用的 lambda(auto作為引數),應該推匯出什么?
您的示例作業正常,唯一的問題是模板推導。您可以static_cast手動使用 lambda SendFunctor<Message>,它可以按預期作業(https://godbolt.org/z/K5eveEM3c)。
uj5u.com熱心網友回復:
lambda 運算式是編譯器為其定義 operator() 的物件(該物件的型別是由編譯器臨時定義的,并且任何 lambda 具有不同的型別)。簡而言之,沒有從 lambda 型別到函式指標的隱式轉換。在這些情況下,我更喜歡使用std::functionwhich 具有足夠的建構式來處理 lambda 運算式。
因此,一種可能的解決方案是將原始函式指標替換為并將lambda 運算式std::function封裝在 a中以傳遞給建構式。std::function
#include <functional>
#include <iostream>
template<typename MsgType>
using SendFunctor = std::function<void(MsgType&)>;
template<typename MsgType>
struct Test {
Test(SendFunctor<MsgType> t) {
MsgType msg;
t(msg);
}
};
struct Message {};
template<typename MsgType>
Test(SendFunctor<MsgType>) -> Test<Message>;
int main()
{
SendFunctor<Message> f = [](Message&) { std::cout << "Hello2" << std::endl; };
Test test(f);
}
這是一個現場測驗
- - 編輯
玩了一會兒,我還通過使用 struct helper 來推斷采用 lambda 運算式的引數來解決您的演繹指南中的歧義,這要歸功于您可以閱讀的完整答案。
這是推斷 lambda 的引數型別的輔助結構。
template<class C>
struct Get_LambdaFirstArg;
template<class C, class R, class Arg>
struct Get_LambdaFirstArg<R(C::*)(Arg&)const>{
using type = Arg;
};
template<class C, class R, class Arg>
struct Get_LambdaFirstArg<R(C::*)(Arg&)>{
using type = Arg;
};
這是為處理 lambda 運算式而定義的新推導指南。
template<typename LambdaType>
Test(LambdaType) -> Test<typename Get_LambdaFirstArg<decltype(&LambdaType::operator())>::type>;
這是一個最小的例子:
#include <functional>
#include <iostream>
template<typename MsgType>
using SendFunctor = std::function<void(MsgType&)>;
template<typename MsgType>
struct Test {
Test(SendFunctor<MsgType> t) {
MsgType msg;
t(msg);
}
};
template<class C>
struct Get_LambdaFirstArg;
template<class C, class R, class Arg>
struct Get_LambdaFirstArg<R(C::*)(Arg&)const>{
using type = Arg;
};
template<class C, class R, class Arg>
struct Get_LambdaFirstArg<R(C::*)(Arg&)>{
using type = Arg;
};
struct Message {};
template<typename MsgType>
Test(SendFunctor<MsgType>) -> Test<Message>;
template<typename LambdaType>
Test(LambdaType) -> Test<typename Get_LambdaFirstArg<decltype(&LambdaType::operator())>::type>;
int main()
{
Test test([](Message&) { std::cout << "Hello2" << std::endl; });
}
這是該示例的實時測驗。
-- 編輯最后我更好地測驗了@apple apple 的答案,看來我做錯了什么。使用 將 lambda 轉換為函式指標并解決演繹指南中的歧義。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/504921.html
標籤:C
上一篇:資料不會從本地存盤中檢索
