
Dear all, Our company makes heavy use of boost libraries. But unfornately some libraries trigger warnings. This is hard to circumvent since we both have level 4 and warnings as error option enabled in Visual Studio 2003. An example is the counting iterator: const std::vector<int> values1(boost::make_counting_iterator(1), boost::make_counting_iterator(10)); gives C4244. This is even harder to supress since the STL is included in the precompiled header. Is it an option to have a good look at this issue for the next release? Note that it is also possible that Plauger's STL is not conforming. Wkr, me

gast128 wrote:
An example is the counting iterator:
const std::vector<int> values1(boost::make_counting_iterator(1), boost::make_counting_iterator(10));
gives C4244. This is even harder to supress since the STL is included in the precompiled header.
This code should really not give you any warnings. (And doesn't on GCC, though I doubt that'll help you.) C4244, so that others don't have to look it up, is the "conversion with possible data loss" warning. This indicates that in VC++, make_counting_iterator returns a counting_iterator<long> or even <__int64>. Can somebody with that compiler post the output of this line? std::cout << typeid(boost::make_counting_iterator(1)).name() << std::endl; A simple workaround for this particular warning ought to be to directly instantiate counting_iterators with their template parameter set correctly. Sebastian Redl

Note: I'm using boost 1.33.1 here Sebastian Redl wrote:
This code should really not give you any warnings. (And doesn't on GCC, though I doubt that'll help you.) C4244, so that others don't have to look it up, is the "conversion with possible data loss" warning. This indicates that in VC++, make_counting_iterator returns a counting_iterator<long> or even <__int64>. Can somebody with that compiler post the output of this line? std::cout << typeid(boost::make_counting_iterator(1)).name() << std::endl;
A simple workaround for this particular warning ought to be to
Using Visual Studio .NET 2003, the output of this was: class boost::counting_iterator<int,struct boost::use_default,struct boost::use_default> as it should be. directly instantiate counting_iterators with their template parameter set correctly.
Sebastian Redl
The problem appears to be when operator += is called on the iterator. Here, the difference_type of the iterator, boost::iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference>::difference_type, which is equal to boost::detail::counting_iterator_base<int,boost::use_default,boost::use_default>::difference, is __int64. The counting_iterator_base uses the following typedef: typedef typename detail::ia_dflt_help< Difference , mpl::eval_if< is_numeric<Incrementable> , numeric_difference<Incrementable> , iterator_difference<Incrementable> > >::type difference; It seems this has been discovered before: http://lists.boost.org/Archives/boost/2004/07/69347.php The actual warnings I received compiling this code were: -------------------------------------------------------- Compiling... BoostTest1.cpp d:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xutility(481) : warning C4244: '+=' : conversion from 'boost::iterators::enabled<__formal>::base<T>::type' to 'std::vector<_Ty>::size_type', possible loss of data with [ __formal=true, T=std::iterator_traits<boost::counting_iterator<int,boost::use_default,boost::use_default>>::difference_type ] and [ _Ty=int ] d:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xutility(498) : see reference to function template instantiation 'void std::_Distance2<_InIt,_Diff>(_RanIt,_RanIt,_Diff &,std::random_access_iterator_tag)' being compiled with [ _InIt=boost::counting_iterator<int,boost::use_default,boost::use_default>, _Diff=std::vector<int>::size_type, _RanIt=boost::counting_iterator<int,boost::use_default,boost::use_default> ] d:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\vector(657) : see reference to function template instantiation 'void std::_Distance<_Iter,std::vector<_Ty>::size_type>(_InIt,_InIt,_Diff &)' being compiled with [ _Iter=boost::counting_iterator<int,boost::use_default,boost::use_default>, _Ty=int, _InIt=boost::counting_iterator<int,boost::use_default,boost::use_default>, _Diff=std::vector<int>::size_type ] d:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\vector(634) : see reference to function template instantiation 'void std::vector<_Ty>::_Insert<_Iter>(std::vector<_Ty>::iterator,_Iter,_Iter,std::forward_iterator_tag)' being compiled with [ _Ty=int, _Iter=boost::counting_iterator<int,boost::use_default,boost::use_default> ] d:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\vector(366) : see reference to function template instantiation 'void std::vector<_Ty>::insert<_Iter>(std::vector<_Ty>::iterator,_Iter,_Iter)' being compiled with [ _Ty=int, _Iter=boost::counting_iterator<int,boost::use_default,boost::use_default> ] d:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\vector(343) : see reference to function template instantiation 'void std::vector<_Ty>::_Construct<_Iter>(_Iter,_Iter,std::input_iterator_tag)' being compiled with [ _Ty=int, _Iter=boost::counting_iterator<int,boost::use_default,boost::use_default> ] g:\Projects\BoostTest1\BoostTest1.cpp(15) : see reference to function template instantiation 'std::vector<_Ty>::vector<boost::counting_iterator<Incrementable,CategoryOrTraversal,Difference>>(_Iter,_Iter)' being compiled with [ _Ty=int, Incrementable=int, CategoryOrTraversal=boost::use_default, Difference=boost::use_default, _Iter =boost::counting_iterator<int,boost::use_default,boost::use_default> ] d:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\boost\iterator\iterator_adaptor.hpp(329) : warning C4244: '+=' : conversion from 'boost::iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference>::difference_type' to 'int', possible loss of data with [ Derived=boost::counting_iterator<int,boost::use_default,boost::use_default>, Value=const boost::mpl::identity<const int>::type, CategoryOrTraversal=boost::mpl::identity<boost::random_access_traversal_tag>::type, Reference=boost::mpl::identity<const int &>::type, Difference=boost::mpl::identity<boost::detail::counting_iterator_base<int,boost::use_default,boost::use_default>::difference>::type ] d:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\boost\iterator\iterator_adaptor.hpp(327) : while compiling class-template member function 'void boost::iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference>::advance(boost::iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference>::difference_type)' with [ Derived=boost::counting_iterator<int,boost::use_default,boost::use_default>, Base=int, Value=const int, Traversal=boost::detail::counting_iterator_base<int,boost::use_default,boost::use_default>::traversal, Reference=const int &, Difference=boost::detail::counting_iterator_base<int,boost::use_default,boost::use_default>::difference, CategoryOrTraversal=boost::mpl::identity<boost::random_access_traversal_tag>::type ] d:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\boost\iterator\counting_iterator.hpp(153) : see reference to class template instantiation 'boost::iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference>' being compiled with [ Derived=boost::counting_iterator<int,boost::use_default,boost::use_default>, Base=int, Val ue=const int, Traversal=boost::detail::counting_iterator_base<int,boost::use_default,boost::use_default>::traversal, Reference=const int &, Difference=boost::detail::counting_iterator_base<int,boost::use_default,boost::use_default>::difference ] g:\Projects\BoostTest1\BoostTest1.cpp(12) : see reference to class template instantiation 'boost::counting_iterator<Incrementable,CategoryOrTraversal,Difference>' being compiled with [ Incrementable=int, CategoryOrTraversal=boost::use_default, Difference=boost::use_default ]

Lee Houghton wrote:
The problem appears to be when operator += is called on the iterator. Here, the difference_type of the iterator, boost::iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference>::difference_type, which is equal to boost::detail::counting_iterator_base<int,boost::use_default,boost::use_default>::difference, is __int64.
OK, that actually makes sense. The typedef searches for the smallest type able to represent all differences between any two numbers of the given type. For signed integers, this is always the next larger signed type. The reason for this is simple: INT_MAX - INT_MIN == UINT_MAX, but INT_MIN - INT_MAX == -UINT_MAX, a number that can only be represented by the next larger signed type. I wonder if this problem is logically solvable, or if a hack (like a static_cast in iterator_adaptor::advance, or perhaps a warning disable) is necessary. Another question is whether this warning should be considered perhaps a bug in VC++. Whatever. Different workaround is to modify boost/iterator/iterator_adaptor.hpp: + #if defined(BOOST_MSVC) + #pragma warning(disable: 4244) + #endif void advance(typename super_t::difference_type n) { BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) m_iterator += n; } + #if defined(BOOST_MSVC) + #pragma warning(default: 4244) + #endif This is potentially unsafe, of course - nothing prevents you from just passing a HUGE value to +=. The likelyhood, though ... well, it's just a workaround. Sebastian Redl

Sebastian Redl <sebastian.redl@getdesigned.at> writes:
Whatever. Different workaround is to modify boost/iterator/iterator_adaptor.hpp:
+ #if defined(BOOST_MSVC) + #pragma warning(disable: 4244) + #endif void advance(typename super_t::difference_type n) {
BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) m_iterator += n; } + #if defined(BOOST_MSVC) + #pragma warning(default: 4244) + #endif
This is potentially unsafe, of course - nothing prevents you from just passing a HUGE value to +=. The likelyhood, though ... well, it's just a workaround.
No static checking (e.g. warning) can protect you from the possibility of runtime overflows in integer operations. The overflow can occur with or without the warning disabled. These "integer size warnings" are nothing more than a nuisance in most generic code. IMO they should be turned off on the command line. Turning them off in individual source files leaves them cluttered with workarounds and #ifdefs. -- Dave Abrahams Boost Consulting www.boost-consulting.com

It looks like that warning is generated due to /W64 (Detect 64-bit portability issues) command line option. If you disable it I bet the warning will go away. Although this option looks helpful, I think it generates false possitives. For example it will generate a warning if you assign a size_t to an unsigned int due to how size_t is defined with this command line option enabled. On Thu, 26 Jan 2006 03:37:33 -0700, gast128 <gast128@hotmail.com> wrote:
Dear all,
Our company makes heavy use of boost libraries. But unfornately some libraries trigger warnings. This is hard to circumvent since we both have level 4 and warnings as error option enabled in Visual Studio 2003.
An example is the counting iterator:
const std::vector<int> values1(boost::make_counting_iterator(1), boost::make_counting_iterator(10));
gives C4244. This is even harder to supress since the STL is included in the precompiled header.
Is it an option to have a good look at this issue for the next release? Note that it is also possible that Plauger's STL is not conforming.
Wkr, me
-- Orhun Birsoy
participants (5)
-
David Abrahams
-
gast128
-
Lee Houghton
-
Orhun Birsoy
-
Sebastian Redl