c++ - std::function implicit type conversion -


using g++ (ubuntu 4.8.5-1ubuntu1) 4.8.5 , compiling g++ -std=c++11 -wall -wextra -wconversion

the following not compile expected:

template <typename t> struct foo {     foo(t t) {} };  struct bar {     bar(foo<float> foo) : foo(foo) {} //trying convert foo<float> foo<double>     foo<double> foo; }; 

the following compiles warning -wconversion, expected:

void foo(float t){} int main() {     foo(3.141592653589794626);     return 0;    } 

however, following compiles no warnings:

#include <functional>  void foo(double t){}  struct bar {     bar(std::function<void(float)> foo) : foo(foo) {} //convert std::function<void(float)> std::function<void(double)>     std::function<void(double)> foo; };  int main(){     bar bar(foo); //convert std::function<void(double)> std::function<void(float)>     bar.foo(3.141592653589794626); //rounded  to: 3.141592741012573     foo(3.141592653589794626);     //not rounded: 3.141592653589794     return 0; } 

clearly automatic conversion float<->double why allowed in third example , not first? why -wconversion not catch this?

(invisible loss of precision problem in number of areas, example when working latitude/longitude).

as elwin arens noted, problem type erasure going on in inner workings of std::function. 1 might suppose quick fix change type in constructor argument double, doesn't prevent user passing in function takes float. example,

void foo(float t) {     std::cout << std::setprecision(15) << std::fixed << t << std::endl; }  struct bar {     bar(std::function<void(double)> foo) : foo(foo) {}     std::function<void(double)> foo; };  int main() {     bar bar(foo);     bar.foo(3.141592653589794626); //rounded  to: 3.141592741012573         foo(3.141592653589794626); //not rounded: 3.141592653589794 } 

compiles file, gives undesired result. 1 fix use template constructor , tmp.

void foo(double t) {     std::cout << std::setprecision(15) << std::fixed << t << std::endl; }  struct bar {     using target_type = double;     using func_type = void(*)(target_type);      template <typename t, typename u = typename std::enable_if<std::is_same<t,func_type>::value,void>::type>     bar(t foo) : foo(foo) {}      std::function<void(target_type)> foo; };  int main() {     bar bar(foo);     bar.foo(3.141592653589794626); //rounded  to: 3.141592741012573         foo(3.141592653589794626); //not rounded: 3.141592653589794 } 

now fails compile if pass in function doesn't match signature of bar::foo. complication have make sure func_type also matches signature of bar::foo if ever changes.


Comments

Popular posts from this blog

wordpress - (T_ENDFOREACH) php error -

Export Excel workseet into txt file using vba - (text and numbers with formulas) -

Using django-mptt to get only the categories that have items -