使用g++ (Ubuntu 4.8.5-1ubuntu1) 4.8.5
与g++ -std=c++11 -Wall -Wextra -Wconversion
的std ::函数隐式类型转换
下无法编译这是预期编译:
template <typename T>
struct Foo {
Foo(T t) {}
};
struct Bar {
Bar(Foo<float> foo) : foo(foo) {} //Trying to convert Foo<float> to Foo<double>
Foo<double> foo;
};
下面的编译与-Wconversion
警告,预期:
void foo(float t){}
int main() {
foo(3.141592653589794626);
return 0;
}
但是,以下编译没有警告:
#include <functional>
void foo(double t){}
struct Bar {
Bar(std::function<void(float)> foo) : foo(foo) {} //Convert std::function<void(float)> to std::function<void(double)>
std::function<void(double)> foo;
};
int main(){
Bar bar(foo); //Convert std::function<void(double)> to std::function<void(float)>
bar.foo(3.141592653589794626); //Rounded to: 3.141592741012573
foo(3.141592653589794626); //Not rounded: 3.141592653589794
return 0;
}
显然,这是一些自动转换float<->double
但为什么它在第三个例子允许的,而不是第一?为什么-Wconversion
不能捕捉到这个?
(精确度的不可见损失在许多方面都是问题,例如在使用纬度/经度时)。
谢谢蒂姆。经过Elwin Arens的回答,我相信在这种情况下Bar的最佳定义是:'template struct Bar {const F&foo}:foo(foo){} \t F &foo; }; '。我不应该一直使用std :: function来开始! –
lenguador
@lenguador请小心使用此解决方案。如果'F'是一个生命周期比被实例化的'Bar'更短的lambda,那么你将会进入不好的地方。我同意这种解决方案可以提供更好的类型安全性,但它也会导致错误的声明:'int meow(float); auto b = Bar(meow);' –
Tim
有什么方法可以确保在编译时提供函数吗?在我的用例中,函数在编译时已知,但我不希望有人错误地传递一个错误的生命周期的lambda。 – lenguador