[英]C++17 Template argument deduction failed
我想模擬計時器,它會定期調用一個函數(回調),因為我寫了以下代碼片段(雖然很幼稚),其中,參數推導在主函數中的 Timer/ <int, int, float> /.. 行失敗。 我正在用 c++17 std 編譯這段代碼。 我該如何解決這個問題? 或者那些必要的論點? 在這方面的任何幫助表示贊賞。
#include <functional>
#include <chrono>
using namespace std::chrono_literals;
template<typename ...Args>
class Timer
{
public:
Timer(std::function<void(Args...)> func, Args&&... args, std::chrono::milliseconds step)
: m_callback{ func },
m_args{ std::forward<Args>(args)... },
m_time{ step },
m_stop{ false },
{ }
private:
std::function<void(Args...)> m_callback;
std::thread m_executer;
std::tuple<Args...> m_args;
std::chrono::milliseconds m_time;
bool m_stop;
};
int main()
{
// Create a timer
auto timer = Timer/*<int, int, float>*/([](int a, int b, float c) { }, 15, 17, 12.0f, 500ms);
return 0;
}
我刪除了與您的問題無關的所有內容(您應該這樣做以使其更容易獲得幫助),這就是我要做的工作。 首先,我在可變參數之前移動了毫秒。 它可能會混淆參數包結束的編譯器,因此您通常希望 ... 成為參數列表中的最后一件事。
其次,由於需要將 lambda 轉換為 std::function 才能匹配,因此 CTAD(類模板 arg 推導)對您不起作用。
如果 main() 按預期將實際的 std::function 傳遞給構造函數,則它可以工作:
auto timer = Timer(
std::function<void(int, int, float)>([](int a, int b, float c) { }),
500ms, 15, 17, 12.0f);
但這可以說比你最初嘗試的更糟糕。
更好的解決方法(有點模糊)是幫助 CTAD 弄清楚您在使用 c++17演繹指南做什么。 這是一個模式匹配說,“如果他們嘗試使用這種語法創建這個類,它真的意味着它是這種類型。”
這是我找到的適合您的指南:
template <typename T, typename... Args>
Timer(T&&, std::chrono::milliseconds, Args...) -> Timer<Args...>;
本指南的作用是說:他們可以將任何 T&& 作為第一個參數傳遞,它只是被忽略,然后是 chrono 毫秒,然后是 Args 包中的更多類型。 鑒於此, Timer 的實際類型(箭頭右側)只是 Timer<Args...> 無論它們是什么。 然后繼續,您的函數只需要可轉換為 std::function 即可。
現在它與您的 lambda 匹配,使用給定的 Args 實例化 Timer,並由此知道它可以將您的 lambda 轉換為 std::function。
這是一個工作示例,減去所有不相關的內容:
#include <functional>
#include <chrono>
using namespace std::chrono_literals;
template<typename ...Args>
struct Timer {
Timer(std::function<void(Args...)> func, std::chrono::milliseconds step, Args&&... args )
{ }
};
template <typename T, typename... Args>
Timer(T&&, std::chrono::milliseconds, Args...) -> Timer<Args...>;
int main() {
auto timer = Timer([](int a, int b, float c) { }, 500ms, 15, 17, 12.0f);
}
編譯器資源管理器: https : //godbolt.org/z/Wa3oK3
這里模板參數推導有兩個問題。 無法從 lambda 參數中推導出std::function
參數,推導僅適用於尾隨參數包。
要解決此問題,您可以更改構造函數的參數順序,如下所示:
Timer(std::function<void(Args...)> func, std::chrono::milliseconds step, Args&&... args)
// ... // ^^^^^^^^^ trailing
並添加扣除指南
template<typename Func, typename ...Args>
Timer(Func, std::chrono::milliseconds, Args&&...) -> Timer<Args...>;
這是一個演示。
請注意警告,您的成員初始值設定項列表與成員聲明的順序不同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.