Unexpected compiler behavior relating to size_t and boost - VisualStudio 2005.

U

Unknownmat

Hello,

I am using Visual Studio 2005 (msvc 8.0, I believe). I am experience
some unexpected compiler warnings that have to do with how integer
types, size_t, and boost interact. I hope that somebody on this list
might know what's going on.

Here is the smallest code I could come up with to reproduce the
behavior:

#include <vector>
#include <functional>
#include <boost/function.hpp>

template< class T >
void test()
{
typedef std::vector< T > TItems;
typedef boost::function< bool (T, T) > TCompFn;
typedef std::vector< std::size_t > TSizes;

TItems data;
TCompFn fn = TCompFn( std::greater< T >() );
fn( data.front(), data.front() ); // NOTE: data is empty - will
cause a runtime error if run
}

int main()
{
test< int >();
test< unsigned >();
}


When I compile this, I get the following warning about the line
"fn( data.front(), data.front() );":
warning C4267: 'argument' : conversion from 'size_t' to 'unsigned
int', possible loss of data

This warning will go away when I do any of the following:
- Comment out EITHER line in the main function.
- Use a 'naked' std::greater< T >, rather than a boost::function<
bool (T, T) >
- comment out the typedef std::vector< std::size_t > TSizes;

I thought that size_t was distinct form the various integer types -
and the compiler warning seems to confirm this - but based on the fact
that commenting out the vector< size_t> typedef removes the warning,
this typedef seems to be stepping on my earlier vector< T > typedef.

Based on the fact that using greater< T > instead of function< bool
(T,T) > fixes the problem -- I wonder if some boost size_t definition
somehow steps on std::size_t?

And finally, I'm completely stumped why commenting out either line in
main() 'fixes' the problem.

Anyway, thanks for your time, any help would be appreciated.

Matt
 
U

Unknownmat

Here is the smallest code I could come up with to reproduce the
behavior:

#include <vector>
#include <functional>
#include <boost/function.hpp>

template< class T >
void test()
{
typedef std::vector< T > TItems;
typedef boost::function< bool (T, T) > TCompFn;
typedef std::vector< std::size_t > TSizes;

TItems data;
TCompFn fn = TCompFn( std::greater< T >() );
fn( data.front(), data.front() ); // NOTE: data is empty - will
cause a runtime error if run

}

int main()
{
test< int >();
test< unsigned >();

}

I was able to reproduce the warning with an even smaller snippet of
code:

#include <vector>
#include <functional>
#include <boost/function.hpp>

int main()
{
std::vector< std::size_t > sizes;
std::vector< unsigned > data;

boost::function< bool (unsigned, unsigned) > fn = std::greater<
unsigned >();
fn( data.front(), 10 );
}

The warning goes away if I comment out the line "std::vector<
std::size_t > sizes;". This behavior baffles me. Any insight would
again be appreciated.

Thanks,
Matt
 
C

Christian Hackl

Unknownmat said:
I was able to reproduce the warning with an even smaller snippet of
code:

#include <vector>
#include <functional>
#include <boost/function.hpp>

int main()
{
std::vector< std::size_t > sizes;
std::vector< unsigned > data;

boost::function< bool (unsigned, unsigned) > fn = std::greater<
unsigned >();
fn( data.front(), 10 );
}

The warning goes away if I comment out the line "std::vector<
std::size_t > sizes;". This behavior baffles me. Any insight would
again be appreciated.

I cannot reproduce C4267 myself with MSVC 8.0 and Boost 1.35.0, not even
with /Wall. I suggest you try microsoft.public.vc.language (which is the
proper place to ask VC-specific questions, anyway).
 
J

Juha Nieminen

Unknownmat said:
I am using Visual Studio 2005 (msvc 8.0, I believe). I am experience
some unexpected compiler warnings that have to do with how integer
types, size_t, and boost interact.

VS2005 has a bug related to this. When you use size_t, it internally
converts it to 'unsigned int'. In some situations it forgets that the
type was actually size_t and only sees it's an 'unsigned int', so when
you eg. assign a size_t value to such a "unsigned int which was a size_t
but VS2005 has forgotten about it", it will give you a warning about
possible data loss (because it only sees that a size_t is being assigned
to an unsigned int, and this triggers its warning about possible loss of
data, as size_t may be bigger than unsigned int in another system).

I don't know if anything can be done about that, except turning the
warning off. (You can turn it off on a per-file basis using a #pragma.)
 
J

James Kanze

VS2005 has a bug related to this. When you use size_t, it internally
converts it to 'unsigned int'. In some situations it forgets that the
type was actually size_t and only sees it's an 'unsigned int',

How is that a bug? size_t is required to be a typedef, not a
real type, and on a lot of 32 bit machines, it is an unsigned
int. Not "gets converted to", but "is".
 
U

Unknownmat

Thanks for the response - it wasn't clear to me that this was a MSVC
specific bug. Perhaps I shouldn't have added that to the title,
except that I knew it would come up (and rightfully so, apparently).

Curiously, are you using VS 2005 with SP1? I've been able to
reproduce this fairly consistently on multiple computers. I'm a bit
surprised that you say that you cannot reproduce it.

Thanks,
Matt
 
U

Unknownmat

Juha said:
VS2005 has a bug related to this. When you use size_t, it internally
converts it to 'unsigned int'. In some situations it forgets that the
type was actually size_t and only sees it's an 'unsigned int', so when
you eg. assign a size_t value to such a "unsigned int which was a size_t
but VS2005 has forgotten about it", it will give you a warning about
possible data loss (because it only sees that a size_t is being assigned
to an unsigned int, and this triggers its warning about possible loss of
data, as size_t may be bigger than unsigned int in another system).

I don't know if anything can be done about that, except turning the
warning off. (You can turn it off on a per-file basis using a #pragma.)

Thanks for the response that helps immensley. Do you happen to have a
Microsoft KB link?

I will do some more digging now that I know that this is VS2005
related. What's interesting to me is that I am very careful about
using size_t - I never need to typecast between unsigned and size_t
(unless I'm forced to by a library API or something). In the example
I posted above, in fact, I'm not even USING the vector< size_t> object
- there's simply no way this object could cause a conversion error.

Thanks,
Matt
 
U

Unknownmat

The warning goes away if I comment out the line "std::vector<
std::size_t > sizes;".  This behavior baffles me.  Any insight would
again be appreciated.

Thanks,
Matt- Hide quoted text -

- Show quoted text -

In case anybody is interested - I figured out what's causing this
issue. Microsoft's "detect 64-bit portability issues" compiler option
causes both false-positives, and false-negatives, and interacts poorly
with templates. This is clearly one of those cases.

Turning off the "/Wp64" switch will eliminate this false warning.

Thanks for the help. Sorry for being OT.

Matt
 
J

Juha Nieminen

Unknownmat said:
What's interesting to me is that I am very careful about
using size_t - I never need to typecast between unsigned and size_t
(unless I'm forced to by a library API or something). In the example
I posted above, in fact, I'm not even USING the vector< size_t> object
- there's simply no way this object could cause a conversion error.

That's the funny side-effect of that bug: Even if there isn't even a
single "int" or "unsigned int" in the entire program, only size_t (and
some template, which is what usually causes the problem), the compiler
will still trigger a warning about an inexistent "unsigned int".

(The problem is understandable because when compiling a 32-bit program
size_t *is* an unsigned int, but other compilers are able to retain the
info that it was, actually, a size_t all the way and they don't give any
warnings.)
 
J

James Kanze

That's the funny side-effect of that bug: Even if there isn't
even a single "int" or "unsigned int" in the entire program,
only size_t (and some template, which is what usually causes
the problem), the compiler will still trigger a warning about
an inexistent "unsigned int".
(The problem is understandable because when compiling a 32-bit
program size_t *is* an unsigned int, but other compilers are
able to retain the info that it was, actually, a size_t all
the way and they don't give any warnings.)

I think you have it backwards. Other compilers simply consider
it an unsigned int (or whatever), and get on with it; they don't
try to treat size_t differently from whatever it is typedef'ed
to.

Which is, of course, what the standard says the compiler should
do.

Of course, there's nothing wrong with keeping the fact that this
unsigned int was originally a size_t, for things like error
messages, e.g. displaying std::vector< size_t ... > instead of
std::vector< unsigned int ... >. But in practice, most don't
seem to: if I write:
std::vector< std::size_t > v ;
v.push_back( 1, 2 ) ;
both g++ and Sun CC complain about an error using a member
function of "std::vector<unsigned int, std::allocator<unsigned
int> >" (g++) or "std::vector<unsigned>" (Sun CC). Only VC++
retains this information, displaying an error in
"std::vector<_Ty>", but later indicating that _Ty=size_t (which
is actually pretty nice---it's nice, too, that both Sun CC and
VC++ omit mentionning the allocator).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top