防止在std::函数中使用不同类型包装lambda
Prevent wrapping lambda in std::function with different types
我有一个类,它的构造函数是std::function<void(T)>
。如果我声明T为double,但向构造函数传递一个带int的lambda,编译器会让我在没有警告的情况下离开。(更新:MSVC发出警告,clang没有)。有可能修改这段代码,使我得到一个编译器错误(w/clang)吗?
我很惊讶这个工作:
#include <functional>
#include <iostream>
template <typename T>
class Thing {
public:
using Handler = std::function<void(T)>;
Thing(Handler handler)
: handler_(handler)
{}
Handler handler_;
};
int main() {
Thing<double> foo([](int bar) { // Conversion to void(int) from void(double)
std::cout << bar;
});
foo.handler_(4.2);
return 0;
}
并在没有警告的情况下编译:
$ clang --std=c++11 -lc++ -Wall -Werror test.cc
$ ./a.out
4
这样的转换似乎会导致不必要的副作用。我无法想象在任何情况下,这种行为都会是人们想要的。
您可以使用一个模板类作为参数,该模板类只允许转换为T
:
template <typename T>
struct Strict {
// This is a bit simplistic, but enough for fundamental types
Strict(T t_) : t(t_) {}
operator T() const { return t; }
template<typename U>
operator U() const = delete;
T t;
};
template <typename T>
class Thing {
public:
using Handler = std::function<void(Strict<T>)>;
//...
};
演示
然而,请注意,使用这种方法,扩大转换不会起到很好的作用:
// doesn't compile
Thing<int> foo{[](long long bar){});
对于未捕获的lambda,您可以依赖于它们衰减为指向函数的指针这一事实
使用此行:
using Handler = void(*)(T);
而不是CCD_ 3的当前定义
这样,除非将参数类型更改为所需类型,否则您将收到错误。
换句话说,这(不)如预期的那样工作:
#include <functional>
#include <iostream>
template <typename T>
class Thing {
public:
using Handler = void(*)(T);
Thing(Handler handler)
: handler_(handler)
{}
Handler handler_;
};
int main() {
// switch the type of bar to double and it will compile
Thing<double> foo([](int bar) {
std::cout << bar;
});
foo.handler_(4.2);
return 0;
}
请注意,如果您有Lambda的捕获列表,则此解决方案将不再有效
无论如何,它解决了问题中所解释的问题。
相关文章:
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 在 lambda 捕获中声明的变量的类型推导
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- 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 吗?