使用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