采用 lambda 的模板类的类型推导
Type deduction for template class taking a lambda
我正在尝试编写一个能够在以后调用没有参数的lambda的类。我期待 C++17 类模板参数推导以避免对工厂函数的需求。但是,尝试实例化对象而不指定类型将失败。我可以使用工厂函数,但我想了解为什么会发生这种情况。
我正在使用 VC++2017,启用了 C++17 工具集。这是预期行为吗?为什么?工厂函数是否可以避免,还是由于模板函数和模板类的类型扣除规则不同而需要?任何帮助都会得到赞赏。
template <typename F>
class WillInvoke
{
public:
WillInvoke(std::decay_t<F> f) : f(std::move(f)) { }
void CallNow() { f(); }
private:
std::decay_t<F> f;
};
template <typename F>
WillInvoke<F> make_WillInvoke(F && f)
{
return WillInvoke<F>(std::forward<F>(f));
}
int main()
{
// OK
auto w = make_WillInvoke([](){ std::cout << "Hello World"; });
w.CallNow();
// Won't compile
WillInvoke w2([](){ std::cout << "Hello World"; }); // No instance of constructor matches argument list
w2.CallNow();
}
这是因为像std::decay<T>::type
这样的成员类型别名是不可扣除的。
template<typename T>
void call_me(std::decay_t<T>) {}
// won't work :(
// call_me(1);
我不认为你的类应该衰减类型。相反,你的类应该声明它需要一个对象类型,并将衰减移动到 make 函数中:
template <typename F> // requires std::is_object_v<F>
class WillInvoke
{
static_assert(std::is_object_v<F>,
"WillInvoke requires F to be an object type"
);
public:
WillInvoke(F f) : f(std::move(f)) { }
void CallNow() { f(); }
private:
F f;
};
template <typename F>
auto make_WillInvoke(F && f) -> WillInvoke<std::decay_t<F>>
{
return WillInvoke<std::decay_t<F>>(std::forward<F>(f));
}
好处是,在 C++20 中,您可以取消注释要求,并让编译器在调用站点中强制执行。
相关文章:
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 在 lambda 捕获中声明的变量的类型推导
- C++ 模板类型的静态 lambda 成员的构造
- Clang 工具,用于提取给定 lambda 类型的 lambda 主体
- 如果 lambda 没有指定的类型,std::function 如何接受 lambda?
- Lambda可以用作非类型模板参数吗
- 如何确定捕获不可复制参数的 lambda 的类型?
- 如何制作可以接受任何类型的参数的 std::函数和 lambda
- C++模板函数中,指定回调函子/lambda 的参数类型,同时仍允许内联?
- 运算符中的不同类型? 具有无捕获,相同的签名,lambda
- 通过参数传递 lambda(无函数类型模板)
- 有没有办法根据 lambda 参数返回类型部分专用化我的模板化函数?
- 如何推导lambda的返回类型
- 尽管显式声明了返回类型,但对lambda的调用是不明确的
- 是否创建具有不同返回类型的lambda
- 防止 lambda 的返回类型扣除
- 在 lambda 函数 g++-4.8 中调用继承的受保护子类型
- 在 lambda 中从引用类型捕获的值的类型,不使用通用捕获
- 我可以让返回类型自动处理具有相同签名但捕获不同内容的 lambda 吗?
- 复制分配C++相同类型的 lambda