C++ C++;17模板参数扣除失败

C++ C++;17模板参数扣除失败,c++,c++11,c++17,C++,C++11,C++17,我想模拟一个计时器,它会周期性地调用一个函数(回调),我写了下面的代码段(虽然很幼稚),其中, 参数推断在行计时器处失败/。。主要功能。我正在用c++17标准编译这段代码。我如何修复它?或者这些论点是必要的? 在此方面的任何帮助都将不胜感激 #include <functional> #include <chrono> using namespace std::chrono_literals; template<typename ...Args> clas

我想模拟一个计时器,它会周期性地调用一个函数(回调),我写了下面的代码段(虽然很幼稚),其中, 参数推断在行计时器处失败/。。主要功能。我正在用c++17标准编译这段代码。我如何修复它?或者这些论点是必要的? 在此方面的任何帮助都将不胜感激

#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;
}
#包括
#包括
使用名称空间std::chrono_文本;
模板
班级计时器
{
公众:
计时器(std::function func,Args&&…Args,std::chrono::毫秒步长)
:m_回调{func},
m_args{std::forward(args)…},
m_time{step},
m_stop{false},
{ }
私人:
std::函数m_回调;
std::线程m_执行器;
std::元组m_参数;
std::chrono::毫秒m_时间;
布尔穆站;
};
int main()
{
//创建一个计时器
自动定时器=定时器/**/([](整数a,整数b,浮点c){},15,17,12.0f,500ms);
返回0;
}

我删去了所有与你的问题无关的内容(你应该这样做,以便更容易获得帮助),下面是我要做的工作。首先,我移动了可变参数前的毫秒数。它可能会混淆编译器参数包的结束位置,因此您通常希望。。。是参数列表中的最后一项

其次,CTAD(类模板arg演绎)不适用于您,因为需要在匹配之前将lambda转换为std::函数

如果main()按预期将一个实际的std::函数传递到构造函数中,那么它可以工作:

auto timer = Timer(
    std::function<void(int, int, float)>([](int a, int b, float c) { }),
    500ms, 15, 17, 12.0f);
自动定时器=定时器(
std::function([](int a,int b,float c){}),
500毫秒,15,17,12.0华氏度);
但这可能比你最初尝试的更糟糕

更好的解决方法是帮助CTAD了解您在使用c++17演绎指南时所做的事情,这一点有点模糊。这是一个模式匹配,它说,“如果他们试图使用这种语法创建这个类,这实际上意味着它是这种类型。”

以下是我为您找到的指南:

template <typename T, typename... Args> 
Timer(T&&, std::chrono::milliseconds, Args...) -> Timer<Args...>;
模板

计时器(T&,std::chrono::microsides,Args…->Timer

模板参数推断有两个问题。无法从lambda参数推断出
std::function
参数,并且推断仅适用于尾随的参数包

要解决此问题,可以更改构造函数参数的顺序,如下所示:

Timer(std::function<void(Args...)> func, std::chrono::milliseconds step, Args&&... args)
 // ...                                                              //  ^^^^^^^^^ trailing 
Timer(std::function func,std::chrono::毫秒步长,Args&&…Args)
// ...                                                              //  ^^^^^^^^^ 拖尾
并添加一个扣减指南

template<typename Func, typename ...Args>
Timer(Func, std::chrono::milliseconds, Args&&...) -> Timer<Args...>;
模板
计时器(Func,std::chrono::毫秒,Args&&…->计时器


请注意警告,您的成员初始值设定项列表与成员声明的顺序不同。

我认为它失败了,因为第一个参数是lambda而不是std::function。谢谢,我没有考虑演绎指南。另外,谢谢我将更正初始值设定项列表顺序谢谢您的详细解释。我会记得发表简短的代码片段,重点放在确切的问题上
template<typename Func, typename ...Args>
Timer(Func, std::chrono::milliseconds, Args&&...) -> Timer<Args...>;