CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Sep 2003
    Location
    Cape Town
    Posts
    18

    Compile errors when porting from VC++ 6 to VC++ .Net

    I have an existing project which we currently compile (successfully) on VC++ 6.0
    I am trying to compile it in VC++ 7 but I get some compile errors which I don't really understand.

    1. std:: vector< MyInfo >::iterator ListIter = ...
    if( ListIter ) { ... }
    I get an error C2451: conditional expression of type 'std::vector<_Ty, Ax>::iterator' is illegal with....
    If I change this to the more explicit: if( ListIter != 0 ), it compiles fine.

    2. char newData[sizeof( MyInfo )];
    std::vector< MyInfo >::iterator ListIter = ...
    memcpy( newData, ListIter, sizeof(MyInfo) );
    I get an error C2664: cannot convert parameter 2 from std::vector<_Ty,_Ax>::iterator to const void * with...

    3. if ( !ListIter ) ...
    get an error C2675: unary '!' : 'std::vector< _Ty, _Ax >::const_iterator' does not define this operator or a conversion to a type acceptable to the predefined operator

    I don't understand why it doesn't compile in VC7 but it does in VC6. Can anyone help?

    Thanks
    Stef

  2. #2
    Join Date
    Sep 2002
    Location
    14° 39'19.65"N / 121° 1'44.34"E
    Posts
    9,815
    In all three cases, your code depends on an undocumented implementation detail of std::vector: That the iterator is implemented as a pointer. Note that this isn't documented anywhere, so your code just accidently compiled under VC++ 6.0.

    So to fix case 1, rewrite the test as you already did (using ListIter != NULL). For case 3, do the same using (ListIter == NULL). For case 2 it's a little harder: I think it is rather dared to use an iterator in a memcpy like that. I don't know why you use memcpy here anyway instead of simply assigning the vector element to a MyInfo object.

  3. #3
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Compile errors when porting from VC++ 6 to VC++ .Net

    Originally posted by SPatten
    I have an existing project which we currently compile (successfully) on VC++ 6.0
    I am trying to compile it in VC++ 7 but I get some compile errors which I don't really understand.

    1. std:: vector< MyInfo >::iterator ListIter = ...
    if( ListIter ) { ... }
    I get an error C2451: conditional expression of type 'std::vector<_Ty, Ax>::iterator' is illegal with....
    If I change this to the more explicit: if( ListIter != 0 ), it compiles fine.
    The compiler is correct -- iterators may not be NULL. Therefore you are relying on undefined and undocumented internals of your implementation of STL.

    There is no such thing defined in the C++ language as a NULL iterator, therefore to have your code compile for all versions of Visual C++, plus any other C++ compiler, you'll have to think up another way to determine if an element doesn't exist. An iterator can equal the end() iterator -- maybe you can rewrite your code using the end() iterator to determine validity.
    2. char newData[sizeof( MyInfo )];
    std::vector< MyInfo >::iterator ListIter = ...
    memcpy( newData, ListIter, sizeof(MyInfo) );
    I get an error C2664: cannot convert parameter 2 from std::vector<_Ty,_Ax>::iterator to const void * with...
    Again, this is incorrect -- the value of an iterator has no use to the program, except when comparing with other iterators (for example, comparing an iterator to end() or begin()). To use them in any other way, such as an argument to memcpy(), is undefined behavior. You can dereference iterators, but other than that, you assume you know nothing about the internals of them (I'm refering to the user of the iterator's point of view -- if you are writing your own iterators, then of course, you need to know the internals of your own iterators). You are assuming that iterators are implemented in a certain way -- your assumptions were incorrect for the newer versions of Visual C++.

    Also, if MyInfo is a non-POD class, usage of memcpy() is illegal and leads to undefined behavior. If MyInfo contains member functions, or contain members that contain member functions, then your code is dangerous and may not work correctly. The memcpy() function is reserved for low-level C compatible structs, types, and arrays, not C++ objects. I don't know exactly what you're trying to do -- maybe you can tell us.
    3. if ( !ListIter ) ...
    get an error C2675: unary '!' : 'std::vector< _Ty, _Ax >::const_iterator' does not define this operator or a conversion to a type acceptable to the predefined operator
    Again, relying on the internals of how the iterator is implemented.

    Regards,

    Paul McKenzie

  4. #4
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,721
    Code:
    std:: vector< MyInfo >::iterator ListIter = ...
    if( ListIter ) { ... }
    if you post what is in the "..." it might be easier come up with
    a correct code, but I assume it is something like this :

    Code:
    if (ListIter != myinfo_vector.end()) {}
    Likewise, I assume #3 should be something like:

    Code:
    if (ListIter == myinfo_vector.end()) ...


    as for # 2, I assume you want something like this :

    Code:
        memcpy( newData, &(*ListIter), sizeof(MyInfo) );
    But, as has already been pointed out, this only works
    under certain circumstances.

  5. #5
    Join Date
    Sep 2003
    Location
    Cape Town
    Posts
    18
    Thanks for your responses.
    I can't answer your question as to why the code was written like this as I didn't write it, but nonetheless with your help I have managed to get it compiling.
    The MyInfo which we are memcpy-ing is a struct and not an object so shouldn't be a problem in this case.

    Thanks for your help
    Stef

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449
    Originally posted by SPatten
    I can't answer your question as to why the code was written like this as I didn't write it, but nonetheless with your help I have managed to get it compiling.
    It looks like the original person who wrote the code did not understand the rules of C++ for what is and isn't valid (sorry if you still work with this person, but I have to comment on what is very bad C++ coding). Also, the goal isn't to just get it to compile, the goal is to make sure what you are compiling is valid C++, and not relying on any assumptions as to the underlying implementation of the library routines and data structures.
    The MyInfo which we are memcpy-ing is a struct and not an object so shouldn't be a problem in this case.
    A struct is not the determining factor as to whether it is safe for memcpy().

    Structs can have member functions also. The determining factor is whether the type is POD (Plain-Old-Data) or non-POD. For the memcpy() to work, all members of the struct must be POD types, the struct must not be derived from a base class, the struct cannot contain member functions, constructors, destructors, etc.

    For example, this struct is non-POD:
    Code:
    struct MyStruct
    {
        CString m;
        int x;
        int y;
    };
    The reason why it is non-POD and can't be used for memcpy() is the CString member, which is non-POD.

    Also, there is no difference between a struct and a class except for the default access specifier for members and inheritance -- for structs, the default is public, for a class, the default is private. A struct can contain member functions, be derived from, etc.

    Regards,

    Paul McKenzie

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured