Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. A strange compiler error C2440

A strange compiler error C2440

Scheduled Pinned Locked Moved C / C++ / MFC
c++helpcsharpgraphicsquestion
11 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    IFREETA
    wrote on last edited by
    #1

    Here is my program.I compile it in Visual C++ .Net(VC7) and get a C2440: // All needed headers were included. #include "stdafx.h" using namespace std; class b { protected: int id; public: b( int i ) : id(i) { cout << "ctor of id:" << id << " was called." << endl; } ~b() { cout << "dtor of id:" << id << " was called." << endl; } b( const b & x) : id(x.id) { } const b operator=( const b & x ) { id=x.id; return *this; } }; typedef auto_ptr<b> pb; typedef vector<pb> vpb; int main( void ) { pb t(new b(1)); vpb v; v.push_back( t );// //error C2440: 'initializing' : cannot convert from 'const pb' to 'std::auto_ptr<_Ty>' with [ _Ty=b ] return 0; } Is it a bug of VC7 or anything wrong in my codes? You don't know what you've got till it's gone.

    D S M 3 Replies Last reply
    0
    • I IFREETA

      Here is my program.I compile it in Visual C++ .Net(VC7) and get a C2440: // All needed headers were included. #include "stdafx.h" using namespace std; class b { protected: int id; public: b( int i ) : id(i) { cout << "ctor of id:" << id << " was called." << endl; } ~b() { cout << "dtor of id:" << id << " was called." << endl; } b( const b & x) : id(x.id) { } const b operator=( const b & x ) { id=x.id; return *this; } }; typedef auto_ptr<b> pb; typedef vector<pb> vpb; int main( void ) { pb t(new b(1)); vpb v; v.push_back( t );// //error C2440: 'initializing' : cannot convert from 'const pb' to 'std::auto_ptr<_Ty>' with [ _Ty=b ] return 0; } Is it a bug of VC7 or anything wrong in my codes? You don't know what you've got till it's gone.

      D Offline
      D Offline
      Daniel Lohmann
      wrote on last edited by
      #2

      Only a shot in the dark (don't have my docs at hand): I assume vector::push_back() takes a const reference to the object type (which is auto_ptr<b> in your case). An auto_ptr contains an ownership flag and if assigning auto_ptrs always the L-value takes ownership. For this the R-value (the auto_ptr you try to insert in your vector) has to be modified, because it's ownerhip flag has to be cleared. And this is not possible because it has been passed as a const reference. The error message could be translated to: error C2440: 'initializing' : cannot convert from 'const std::auto_ptr<_Ty>' to 'std::auto_ptr<_Ty>' with [ _Ty=b ] which makes the problem a bit more obvious. (BTW: Does anybody know why the the C++ standard comitee did not made the ownership flag of an auto_ptr mutable, so it could be modified even in const objects?) -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )

      S I 3 Replies Last reply
      0
      • D Daniel Lohmann

        Only a shot in the dark (don't have my docs at hand): I assume vector::push_back() takes a const reference to the object type (which is auto_ptr<b> in your case). An auto_ptr contains an ownership flag and if assigning auto_ptrs always the L-value takes ownership. For this the R-value (the auto_ptr you try to insert in your vector) has to be modified, because it's ownerhip flag has to be cleared. And this is not possible because it has been passed as a const reference. The error message could be translated to: error C2440: 'initializing' : cannot convert from 'const std::auto_ptr<_Ty>' to 'std::auto_ptr<_Ty>' with [ _Ty=b ] which makes the problem a bit more obvious. (BTW: Does anybody know why the the C++ standard comitee did not made the ownership flag of an auto_ptr mutable, so it could be modified even in const objects?) -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )

        S Offline
        S Offline
        Stuart Dootson
        wrote on last edited by
        #3

        You're dead right - it's because the auto_ptr copy constructor takes a non-const reference. The reason it's like that (i.e. not using mutable on the ownership flag) is that containers require that their content elements can be copied without altering the element being copied. For example (and I'm quoting Herb Sutter's Exceptional C++), sort algorithms (particularly those based on partitioning & sorting, I suspect) take copies of elements of containers. This would result in the element being deleted, but it's reference still being in the container. auto_ptr is really best used as a scoped pointer container, i.e. without transfer of ownership. It does help make things easier then, especially with helping to ensure exception safety. Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

        D 1 Reply Last reply
        0
        • D Daniel Lohmann

          Only a shot in the dark (don't have my docs at hand): I assume vector::push_back() takes a const reference to the object type (which is auto_ptr<b> in your case). An auto_ptr contains an ownership flag and if assigning auto_ptrs always the L-value takes ownership. For this the R-value (the auto_ptr you try to insert in your vector) has to be modified, because it's ownerhip flag has to be cleared. And this is not possible because it has been passed as a const reference. The error message could be translated to: error C2440: 'initializing' : cannot convert from 'const std::auto_ptr<_Ty>' to 'std::auto_ptr<_Ty>' with [ _Ty=b ] which makes the problem a bit more obvious. (BTW: Does anybody know why the the C++ standard comitee did not made the ownership flag of an auto_ptr mutable, so it could be modified even in const objects?) -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )

          I Offline
          I Offline
          IFREETA
          wrote on last edited by
          #4

          You're right. The error message confused me. I thought the compiler cannot translate 'pb' to 'std::auto_ptr<_Ty>' or doesn't support nested templates or anything like that. It seems I should provide a const constructor for auto_ptr by myself. Thanks.:) -------------------------------- You don't know what you've got till it's gone.

          D 1 Reply Last reply
          0
          • D Daniel Lohmann

            Only a shot in the dark (don't have my docs at hand): I assume vector::push_back() takes a const reference to the object type (which is auto_ptr<b> in your case). An auto_ptr contains an ownership flag and if assigning auto_ptrs always the L-value takes ownership. For this the R-value (the auto_ptr you try to insert in your vector) has to be modified, because it's ownerhip flag has to be cleared. And this is not possible because it has been passed as a const reference. The error message could be translated to: error C2440: 'initializing' : cannot convert from 'const std::auto_ptr<_Ty>' to 'std::auto_ptr<_Ty>' with [ _Ty=b ] which makes the problem a bit more obvious. (BTW: Does anybody know why the the C++ standard comitee did not made the ownership flag of an auto_ptr mutable, so it could be modified even in const objects?) -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )

            I Offline
            I Offline
            IFREETA
            wrote on last edited by
            #5

            ... // in the header <vector> void _Insert_n(iterator _Where, size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where _Ty _Tmp = _Val; // in case _Val is in sequence // C2440 was actually raised here size_type _Capacity = capacity(); ... It seems that the compiler could not find the operator=, but a copy constructor and the operator= have been present in the header :template<class _Ty> class auto_ptr { // wrap an object pointer to ensure destruction public: typedef _Ty element_type; explicit auto_ptr(_Ty *_Ptr = 0) _THROW0() : _Myptr(_Ptr) { // construct from object pointer } auto_ptr(auto_ptr<_Ty>& _Right) _THROW0() : _Myptr(_Right.release()) { // construct by assuming pointer from _Right auto_ptr } auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0() : _Myptr(_Right._Ref.release()) { // construct by assuming pointer from _Right auto_ptr_ref } ... auto_ptr<_Ty>& operator=(auto_ptr<_Ty>& _Right) _THROW0() { // assign compatible _Right (assume pointer) reset(_Right.release()); return (*this); } ...
            The compiler just ignored them. ------------- You don't know what you've got till it's gone.

            D S 2 Replies Last reply
            0
            • I IFREETA

              You're right. The error message confused me. I thought the compiler cannot translate 'pb' to 'std::auto_ptr<_Ty>' or doesn't support nested templates or anything like that. It seems I should provide a const constructor for auto_ptr by myself. Thanks.:) -------------------------------- You don't know what you've got till it's gone.

              D Offline
              D Offline
              dlhson
              wrote on last edited by
              #6

              Be careful later ! dlhson2001@yahoo.com

              1 Reply Last reply
              0
              • S Stuart Dootson

                You're dead right - it's because the auto_ptr copy constructor takes a non-const reference. The reason it's like that (i.e. not using mutable on the ownership flag) is that containers require that their content elements can be copied without altering the element being copied. For example (and I'm quoting Herb Sutter's Exceptional C++), sort algorithms (particularly those based on partitioning & sorting, I suspect) take copies of elements of containers. This would result in the element being deleted, but it's reference still being in the container. auto_ptr is really best used as a scoped pointer container, i.e. without transfer of ownership. It does help make things easier then, especially with helping to ensure exception safety. Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

                D Offline
                D Offline
                Daniel Lohmann
                wrote on last edited by
                #7

                Thanks Stuart, that surly makes sense and is, if one thinks a bit about it, rather obvious. -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )

                1 Reply Last reply
                0
                • I IFREETA

                  ... // in the header <vector> void _Insert_n(iterator _Where, size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where _Ty _Tmp = _Val; // in case _Val is in sequence // C2440 was actually raised here size_type _Capacity = capacity(); ... It seems that the compiler could not find the operator=, but a copy constructor and the operator= have been present in the header :template<class _Ty> class auto_ptr { // wrap an object pointer to ensure destruction public: typedef _Ty element_type; explicit auto_ptr(_Ty *_Ptr = 0) _THROW0() : _Myptr(_Ptr) { // construct from object pointer } auto_ptr(auto_ptr<_Ty>& _Right) _THROW0() : _Myptr(_Right.release()) { // construct by assuming pointer from _Right auto_ptr } auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0() : _Myptr(_Right._Ref.release()) { // construct by assuming pointer from _Right auto_ptr_ref } ... auto_ptr<_Ty>& operator=(auto_ptr<_Ty>& _Right) _THROW0() { // assign compatible _Right (assume pointer) reset(_Right.release()); return (*this); } ...
                  The compiler just ignored them. ------------- You don't know what you've got till it's gone.

                  D Offline
                  D Offline
                  Daniel Lohmann
                  wrote on last edited by
                  #8

                  Did you read the posting of Stuart to this topic? It is nearly impossible to use auto_ptr in STL containers (and any other kind of container), because you run into a bunch of problems :( -- Daniel Lohmann http://www.losoft.de (Hey, this page is worth looking! You can find some free and handy NT tools there :-D )

                  1 Reply Last reply
                  0
                  • I IFREETA

                    ... // in the header <vector> void _Insert_n(iterator _Where, size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where _Ty _Tmp = _Val; // in case _Val is in sequence // C2440 was actually raised here size_type _Capacity = capacity(); ... It seems that the compiler could not find the operator=, but a copy constructor and the operator= have been present in the header :template<class _Ty> class auto_ptr { // wrap an object pointer to ensure destruction public: typedef _Ty element_type; explicit auto_ptr(_Ty *_Ptr = 0) _THROW0() : _Myptr(_Ptr) { // construct from object pointer } auto_ptr(auto_ptr<_Ty>& _Right) _THROW0() : _Myptr(_Right.release()) { // construct by assuming pointer from _Right auto_ptr } auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0() : _Myptr(_Right._Ref.release()) { // construct by assuming pointer from _Right auto_ptr_ref } ... auto_ptr<_Ty>& operator=(auto_ptr<_Ty>& _Right) _THROW0() { // assign compatible _Right (assume pointer) reset(_Right.release()); return (*this); } ...
                    The compiler just ignored them. ------------- You don't know what you've got till it's gone.

                    S Offline
                    S Offline
                    Stuart Dootson
                    wrote on last edited by
                    #9

                    Noooo - not quite. If you look at the vector definition, void _Insert_n(iterator _Where, size_type _Count, **const** _Ty& _Val), it takes a const reference. BUT - in auto_ptr, none of the assignment operators/coy constructors take a const reference parameter. As you cannot implicitly convert const to non-const, the compiler cannot use these operators! It is that simple really, honest!:) Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

                    1 Reply Last reply
                    0
                    • I IFREETA

                      Here is my program.I compile it in Visual C++ .Net(VC7) and get a C2440: // All needed headers were included. #include "stdafx.h" using namespace std; class b { protected: int id; public: b( int i ) : id(i) { cout << "ctor of id:" << id << " was called." << endl; } ~b() { cout << "dtor of id:" << id << " was called." << endl; } b( const b & x) : id(x.id) { } const b operator=( const b & x ) { id=x.id; return *this; } }; typedef auto_ptr<b> pb; typedef vector<pb> vpb; int main( void ) { pb t(new b(1)); vpb v; v.push_back( t );// //error C2440: 'initializing' : cannot convert from 'const pb' to 'std::auto_ptr<_Ty>' with [ _Ty=b ] return 0; } Is it a bug of VC7 or anything wrong in my codes? You don't know what you've got till it's gone.

                      S Offline
                      S Offline
                      Stuart Dootson
                      wrote on last edited by
                      #10

                      Futher to my other replies - if you want to use smart pointers in STL containers, I'd suggest you use the Boost shared_ptr class. Go to www.boost.org[^]. There's a download for the whole library there. There's a whole lot more than just smart pointers as well... Stuart Dootson 'Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p'

                      1 Reply Last reply
                      0
                      • I IFREETA

                        Here is my program.I compile it in Visual C++ .Net(VC7) and get a C2440: // All needed headers were included. #include "stdafx.h" using namespace std; class b { protected: int id; public: b( int i ) : id(i) { cout << "ctor of id:" << id << " was called." << endl; } ~b() { cout << "dtor of id:" << id << " was called." << endl; } b( const b & x) : id(x.id) { } const b operator=( const b & x ) { id=x.id; return *this; } }; typedef auto_ptr<b> pb; typedef vector<pb> vpb; int main( void ) { pb t(new b(1)); vpb v; v.push_back( t );// //error C2440: 'initializing' : cannot convert from 'const pb' to 'std::auto_ptr<_Ty>' with [ _Ty=b ] return 0; } Is it a bug of VC7 or anything wrong in my codes? You don't know what you've got till it's gone.

                        M Offline
                        M Offline
                        Mike Nordell
                        wrote on last edited by
                        #11

                        You know this code will crash and burn? Don't ever use auto_ptr in collections. Have a look at some other pointer type such as shared_ptr from the BOOST library.

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups