Does the compiler not warn about loss of accuracy?

Recently, I have been playing with C ++ 11 and came up with the following sum function:

template <typename T> inline T sum(const std::function<T (int)> &f, int initial, int end) { T retval = 0; for(int k = initial; k <= end; k++) { retval += f(k); } return retval; } 

The idea is that I can pass in a lambda function and therefore have a neat and readable function for mathematical sums. Then I tried the following:

 int main() { std::array<double, 2> arr1 = {{ 0.5, 1.5 }}, arr2 = {{ 1.5, -0.5 }}; auto n = sum<int>([&](int k) { return arr1[k]*arr2[k]; }, // Precision loss! 0, 1); return 0; } 

I compiled this with g ++ 4.6.3: g++ -Wall -pedantic -std=c++0x -o test main.cpp and does not give any warnings about accuracy losses that I noticed in the source code comment.

It is largely given here that sum<int> is a bad thing, but it may not be so obvious in more complex contexts. If the compiler did not notice that the return value of my lambda function is double and warns me that I lose accuracy when I click on int ? Is there a specific reason this is not the case?

+6
source share
3 answers

It seems quite reasonable. You tell the compiler not to worry about the output of the template argument (i.e. use sum<double> ), but instead, we are talking directly about using sum<int> . This is as good as an explicit cast.

[Edit] How about

 template <typename F> auto sum(F const& f, int initial, int end) -> decltype(f(initial)) { auto retval = f(initial++); while(initial <= end) { retval += f(initial++); } return retval; } 
+5
source

VS11 issues a warning:

Warning 1 warning C4189: 'n': local variable initialized but not specified

Warning 2 warning C4244: '+ =': conversion from 'double' to 'int', possible data loss

Edit, actually this warning is to use the code:

 template <typename T,typename Func> inline T sum(Func f, int initial, int end) 

You get another conversion error warning if you use std::function<T (int)> , so VS is still good at this problem. (IMO, you should usually use functors as a template type, not std :: function)

Even clang with -Weverything does not warn about this (Edit: although I cannot check the version of std :: function with clang ATM). It seems that something can be improved.

I get this strange warning, though:

 ConsoleApplication1.cpp:15:51: warning: will never be executed [-Wunreachable-code] auto n = sum<int>([&](int k) { return arr1[k]*arr2[k]; }, // Precision loss! ^~~~ 
+2
source

If you disable the functor and change the line retval += f(k); on retval += T { f(k) }; in the following way:

 // Machinery to allow caller to indifferently use // sum(f, i, j) and sum<R>(f, i, j) struct deduced {}; template< typename Request = deduced , typename Functor , typename Ret = typename std::conditional< std::is_same<Request, deduced>::value , typename std::result_of<Functor&(int)>::type , Request >::type > inline Ret sum(Functor f, int initial, int end) { Ret retval = 0; for(int k = initial; k <= end; k++) { retval += Ret { f(k) }; } return retval; } 

then, instead of relying on the compiler’s willingness to warn, you are forced to emit diagnostics, since narrowing the conversion is prohibited in the list initialization (i.e., initialization using curly braces).

I don't think there is a reliable way if you restrict the std::function<Sig> functor. It depends entirely on how the implementation wrote std::function when it issues warnings to narrow conversions and even if it warns about its own code.

+1
source

Source: https://habr.com/ru/post/913035/


All Articles