Why is constness not enforced for pointers?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
11
down vote

favorite
1












Consider the following code snippet:



class A

public:

void nonConstFun()



;

class B

private:

A a_;
A * pA_;

public:

void fun() const

pA_->nonConstFun();
//a_.nonConstFun(); // Gives const related error

;

int main()

B b;
b.fun();



Here I am expecting the compiler to fail the compilation for lack of constness for calling A::nonConstFun() inside B::fun() irrespective of the type of A object.



However the compiler complains for the object, but not for the pointer. Why?
I am using VS2017 on Windows 10.










share|improve this question



























    up vote
    11
    down vote

    favorite
    1












    Consider the following code snippet:



    class A

    public:

    void nonConstFun()



    ;

    class B

    private:

    A a_;
    A * pA_;

    public:

    void fun() const

    pA_->nonConstFun();
    //a_.nonConstFun(); // Gives const related error

    ;

    int main()

    B b;
    b.fun();



    Here I am expecting the compiler to fail the compilation for lack of constness for calling A::nonConstFun() inside B::fun() irrespective of the type of A object.



    However the compiler complains for the object, but not for the pointer. Why?
    I am using VS2017 on Windows 10.










    share|improve this question

























      up vote
      11
      down vote

      favorite
      1









      up vote
      11
      down vote

      favorite
      1






      1





      Consider the following code snippet:



      class A

      public:

      void nonConstFun()



      ;

      class B

      private:

      A a_;
      A * pA_;

      public:

      void fun() const

      pA_->nonConstFun();
      //a_.nonConstFun(); // Gives const related error

      ;

      int main()

      B b;
      b.fun();



      Here I am expecting the compiler to fail the compilation for lack of constness for calling A::nonConstFun() inside B::fun() irrespective of the type of A object.



      However the compiler complains for the object, but not for the pointer. Why?
      I am using VS2017 on Windows 10.










      share|improve this question















      Consider the following code snippet:



      class A

      public:

      void nonConstFun()



      ;

      class B

      private:

      A a_;
      A * pA_;

      public:

      void fun() const

      pA_->nonConstFun();
      //a_.nonConstFun(); // Gives const related error

      ;

      int main()

      B b;
      b.fun();



      Here I am expecting the compiler to fail the compilation for lack of constness for calling A::nonConstFun() inside B::fun() irrespective of the type of A object.



      However the compiler complains for the object, but not for the pointer. Why?
      I am using VS2017 on Windows 10.







      c++ pointers const






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 9 mins ago









      Boann

      35.8k1285116




      35.8k1285116










      asked 2 hours ago









      Arun

      1,15621431




      1,15621431






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          15
          down vote



          accepted










          It is enforced.



          If you try changing the pointer, the compiler will not let you.



          The thing that the pointer points to, however, is a different conversation.



          Remember, T* const and T const* are not the same thing!



          You can protect that by either actually making it A const*, or simply by writing your function in the manner that is appropriate.






          share|improve this answer
















          • 3




            I think the question is why doesn't the function's const qualifier protect pointed to objects just as much as the pointer itself. Unfortunately if you make A const* then non const functions can't modify the object. This is a known "flaw/feature" of C++. Although the "why" of it is probably too "opinion" based for SO.
            – Galik
            2 hours ago






          • 3




            @Galik the why is explained by T* const and T const* are not the same thing!. As for the "flaw" - it's not a flaw. It's up to the programmer to decide if the object pointed by the pointer is logically inside the object B or if it logically external, because physically it is external. Modifying the *pa doesn't modify the object B in any physical way. The shortcoming of C++ is that it doesn't offer an easy way to represent a logicial belonging, which is in the process of fixing with propagate_const.
            – bolov
            2 hours ago











          • @bolov I think your comment to me here is the closest we have so far to actually answering the question. I already upvoted your answer for the new information it provided but it might be worth copying some of the substance (the design trade-offs) from your comment to me into your answer?
            – Galik
            2 hours ago











          • @Galik ok, done
            – bolov
            1 hour ago

















          up vote
          19
          down vote













          The other answers explain the T* const vs T const which is what is happening. But it important to understand the implication of this beyond just the mere syntax.



          When you have a T* inside a structure the pointer is inside the object, but the pointed object is physically outside of the struct. That is why for a const object with a T* member it not allowed to modify the pointer, but it is allowed to modify the pointed object - because physically the pointed object is outside the enclosing object.



          And it is up to the programmer to decide if the pointed object is logically part of the enclosing object (and as such should share constness with the enclosing) or if it is logically an external entity.



          The shortcoming of C++ is that it doesn't offer an easy way to express a logical constness as stated above (what you actually expected from your code).



          This is known and for this exact purpose there is an experimental class which is not yet standard propagate_const




          std::experimental::propagate_const is a const-propagating wrapper for
          pointers and pointer-like objects. It treats the wrapped pointer as a
          pointer to const when accessed through a const access path, hence the
          name.




          struct B

          A a_;
          std::experimental::propagate_const<A *> pA_;

          void fun()

          pA_->nonConstFun(); // OK

          void fun() const

          // pA_->nonConstFun(); // compilation error

          ;





          share|improve this answer






















            Your Answer





            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52607625%2fwhy-is-constness-not-enforced-for-pointers%23new-answer', 'question_page');

            );

            Post as a guest






























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            15
            down vote



            accepted










            It is enforced.



            If you try changing the pointer, the compiler will not let you.



            The thing that the pointer points to, however, is a different conversation.



            Remember, T* const and T const* are not the same thing!



            You can protect that by either actually making it A const*, or simply by writing your function in the manner that is appropriate.






            share|improve this answer
















            • 3




              I think the question is why doesn't the function's const qualifier protect pointed to objects just as much as the pointer itself. Unfortunately if you make A const* then non const functions can't modify the object. This is a known "flaw/feature" of C++. Although the "why" of it is probably too "opinion" based for SO.
              – Galik
              2 hours ago






            • 3




              @Galik the why is explained by T* const and T const* are not the same thing!. As for the "flaw" - it's not a flaw. It's up to the programmer to decide if the object pointed by the pointer is logically inside the object B or if it logically external, because physically it is external. Modifying the *pa doesn't modify the object B in any physical way. The shortcoming of C++ is that it doesn't offer an easy way to represent a logicial belonging, which is in the process of fixing with propagate_const.
              – bolov
              2 hours ago











            • @bolov I think your comment to me here is the closest we have so far to actually answering the question. I already upvoted your answer for the new information it provided but it might be worth copying some of the substance (the design trade-offs) from your comment to me into your answer?
              – Galik
              2 hours ago











            • @Galik ok, done
              – bolov
              1 hour ago














            up vote
            15
            down vote



            accepted










            It is enforced.



            If you try changing the pointer, the compiler will not let you.



            The thing that the pointer points to, however, is a different conversation.



            Remember, T* const and T const* are not the same thing!



            You can protect that by either actually making it A const*, or simply by writing your function in the manner that is appropriate.






            share|improve this answer
















            • 3




              I think the question is why doesn't the function's const qualifier protect pointed to objects just as much as the pointer itself. Unfortunately if you make A const* then non const functions can't modify the object. This is a known "flaw/feature" of C++. Although the "why" of it is probably too "opinion" based for SO.
              – Galik
              2 hours ago






            • 3




              @Galik the why is explained by T* const and T const* are not the same thing!. As for the "flaw" - it's not a flaw. It's up to the programmer to decide if the object pointed by the pointer is logically inside the object B or if it logically external, because physically it is external. Modifying the *pa doesn't modify the object B in any physical way. The shortcoming of C++ is that it doesn't offer an easy way to represent a logicial belonging, which is in the process of fixing with propagate_const.
              – bolov
              2 hours ago











            • @bolov I think your comment to me here is the closest we have so far to actually answering the question. I already upvoted your answer for the new information it provided but it might be worth copying some of the substance (the design trade-offs) from your comment to me into your answer?
              – Galik
              2 hours ago











            • @Galik ok, done
              – bolov
              1 hour ago












            up vote
            15
            down vote



            accepted







            up vote
            15
            down vote



            accepted






            It is enforced.



            If you try changing the pointer, the compiler will not let you.



            The thing that the pointer points to, however, is a different conversation.



            Remember, T* const and T const* are not the same thing!



            You can protect that by either actually making it A const*, or simply by writing your function in the manner that is appropriate.






            share|improve this answer












            It is enforced.



            If you try changing the pointer, the compiler will not let you.



            The thing that the pointer points to, however, is a different conversation.



            Remember, T* const and T const* are not the same thing!



            You can protect that by either actually making it A const*, or simply by writing your function in the manner that is appropriate.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 2 hours ago









            Lightness Races in Orbit

            272k48436748




            272k48436748







            • 3




              I think the question is why doesn't the function's const qualifier protect pointed to objects just as much as the pointer itself. Unfortunately if you make A const* then non const functions can't modify the object. This is a known "flaw/feature" of C++. Although the "why" of it is probably too "opinion" based for SO.
              – Galik
              2 hours ago






            • 3




              @Galik the why is explained by T* const and T const* are not the same thing!. As for the "flaw" - it's not a flaw. It's up to the programmer to decide if the object pointed by the pointer is logically inside the object B or if it logically external, because physically it is external. Modifying the *pa doesn't modify the object B in any physical way. The shortcoming of C++ is that it doesn't offer an easy way to represent a logicial belonging, which is in the process of fixing with propagate_const.
              – bolov
              2 hours ago











            • @bolov I think your comment to me here is the closest we have so far to actually answering the question. I already upvoted your answer for the new information it provided but it might be worth copying some of the substance (the design trade-offs) from your comment to me into your answer?
              – Galik
              2 hours ago











            • @Galik ok, done
              – bolov
              1 hour ago












            • 3




              I think the question is why doesn't the function's const qualifier protect pointed to objects just as much as the pointer itself. Unfortunately if you make A const* then non const functions can't modify the object. This is a known "flaw/feature" of C++. Although the "why" of it is probably too "opinion" based for SO.
              – Galik
              2 hours ago






            • 3




              @Galik the why is explained by T* const and T const* are not the same thing!. As for the "flaw" - it's not a flaw. It's up to the programmer to decide if the object pointed by the pointer is logically inside the object B or if it logically external, because physically it is external. Modifying the *pa doesn't modify the object B in any physical way. The shortcoming of C++ is that it doesn't offer an easy way to represent a logicial belonging, which is in the process of fixing with propagate_const.
              – bolov
              2 hours ago











            • @bolov I think your comment to me here is the closest we have so far to actually answering the question. I already upvoted your answer for the new information it provided but it might be worth copying some of the substance (the design trade-offs) from your comment to me into your answer?
              – Galik
              2 hours ago











            • @Galik ok, done
              – bolov
              1 hour ago







            3




            3




            I think the question is why doesn't the function's const qualifier protect pointed to objects just as much as the pointer itself. Unfortunately if you make A const* then non const functions can't modify the object. This is a known "flaw/feature" of C++. Although the "why" of it is probably too "opinion" based for SO.
            – Galik
            2 hours ago




            I think the question is why doesn't the function's const qualifier protect pointed to objects just as much as the pointer itself. Unfortunately if you make A const* then non const functions can't modify the object. This is a known "flaw/feature" of C++. Although the "why" of it is probably too "opinion" based for SO.
            – Galik
            2 hours ago




            3




            3




            @Galik the why is explained by T* const and T const* are not the same thing!. As for the "flaw" - it's not a flaw. It's up to the programmer to decide if the object pointed by the pointer is logically inside the object B or if it logically external, because physically it is external. Modifying the *pa doesn't modify the object B in any physical way. The shortcoming of C++ is that it doesn't offer an easy way to represent a logicial belonging, which is in the process of fixing with propagate_const.
            – bolov
            2 hours ago





            @Galik the why is explained by T* const and T const* are not the same thing!. As for the "flaw" - it's not a flaw. It's up to the programmer to decide if the object pointed by the pointer is logically inside the object B or if it logically external, because physically it is external. Modifying the *pa doesn't modify the object B in any physical way. The shortcoming of C++ is that it doesn't offer an easy way to represent a logicial belonging, which is in the process of fixing with propagate_const.
            – bolov
            2 hours ago













            @bolov I think your comment to me here is the closest we have so far to actually answering the question. I already upvoted your answer for the new information it provided but it might be worth copying some of the substance (the design trade-offs) from your comment to me into your answer?
            – Galik
            2 hours ago





            @bolov I think your comment to me here is the closest we have so far to actually answering the question. I already upvoted your answer for the new information it provided but it might be worth copying some of the substance (the design trade-offs) from your comment to me into your answer?
            – Galik
            2 hours ago













            @Galik ok, done
            – bolov
            1 hour ago




            @Galik ok, done
            – bolov
            1 hour ago












            up vote
            19
            down vote













            The other answers explain the T* const vs T const which is what is happening. But it important to understand the implication of this beyond just the mere syntax.



            When you have a T* inside a structure the pointer is inside the object, but the pointed object is physically outside of the struct. That is why for a const object with a T* member it not allowed to modify the pointer, but it is allowed to modify the pointed object - because physically the pointed object is outside the enclosing object.



            And it is up to the programmer to decide if the pointed object is logically part of the enclosing object (and as such should share constness with the enclosing) or if it is logically an external entity.



            The shortcoming of C++ is that it doesn't offer an easy way to express a logical constness as stated above (what you actually expected from your code).



            This is known and for this exact purpose there is an experimental class which is not yet standard propagate_const




            std::experimental::propagate_const is a const-propagating wrapper for
            pointers and pointer-like objects. It treats the wrapped pointer as a
            pointer to const when accessed through a const access path, hence the
            name.




            struct B

            A a_;
            std::experimental::propagate_const<A *> pA_;

            void fun()

            pA_->nonConstFun(); // OK

            void fun() const

            // pA_->nonConstFun(); // compilation error

            ;





            share|improve this answer


























              up vote
              19
              down vote













              The other answers explain the T* const vs T const which is what is happening. But it important to understand the implication of this beyond just the mere syntax.



              When you have a T* inside a structure the pointer is inside the object, but the pointed object is physically outside of the struct. That is why for a const object with a T* member it not allowed to modify the pointer, but it is allowed to modify the pointed object - because physically the pointed object is outside the enclosing object.



              And it is up to the programmer to decide if the pointed object is logically part of the enclosing object (and as such should share constness with the enclosing) or if it is logically an external entity.



              The shortcoming of C++ is that it doesn't offer an easy way to express a logical constness as stated above (what you actually expected from your code).



              This is known and for this exact purpose there is an experimental class which is not yet standard propagate_const




              std::experimental::propagate_const is a const-propagating wrapper for
              pointers and pointer-like objects. It treats the wrapped pointer as a
              pointer to const when accessed through a const access path, hence the
              name.




              struct B

              A a_;
              std::experimental::propagate_const<A *> pA_;

              void fun()

              pA_->nonConstFun(); // OK

              void fun() const

              // pA_->nonConstFun(); // compilation error

              ;





              share|improve this answer
























                up vote
                19
                down vote










                up vote
                19
                down vote









                The other answers explain the T* const vs T const which is what is happening. But it important to understand the implication of this beyond just the mere syntax.



                When you have a T* inside a structure the pointer is inside the object, but the pointed object is physically outside of the struct. That is why for a const object with a T* member it not allowed to modify the pointer, but it is allowed to modify the pointed object - because physically the pointed object is outside the enclosing object.



                And it is up to the programmer to decide if the pointed object is logically part of the enclosing object (and as such should share constness with the enclosing) or if it is logically an external entity.



                The shortcoming of C++ is that it doesn't offer an easy way to express a logical constness as stated above (what you actually expected from your code).



                This is known and for this exact purpose there is an experimental class which is not yet standard propagate_const




                std::experimental::propagate_const is a const-propagating wrapper for
                pointers and pointer-like objects. It treats the wrapped pointer as a
                pointer to const when accessed through a const access path, hence the
                name.




                struct B

                A a_;
                std::experimental::propagate_const<A *> pA_;

                void fun()

                pA_->nonConstFun(); // OK

                void fun() const

                // pA_->nonConstFun(); // compilation error

                ;





                share|improve this answer














                The other answers explain the T* const vs T const which is what is happening. But it important to understand the implication of this beyond just the mere syntax.



                When you have a T* inside a structure the pointer is inside the object, but the pointed object is physically outside of the struct. That is why for a const object with a T* member it not allowed to modify the pointer, but it is allowed to modify the pointed object - because physically the pointed object is outside the enclosing object.



                And it is up to the programmer to decide if the pointed object is logically part of the enclosing object (and as such should share constness with the enclosing) or if it is logically an external entity.



                The shortcoming of C++ is that it doesn't offer an easy way to express a logical constness as stated above (what you actually expected from your code).



                This is known and for this exact purpose there is an experimental class which is not yet standard propagate_const




                std::experimental::propagate_const is a const-propagating wrapper for
                pointers and pointer-like objects. It treats the wrapped pointer as a
                pointer to const when accessed through a const access path, hence the
                name.




                struct B

                A a_;
                std::experimental::propagate_const<A *> pA_;

                void fun()

                pA_->nonConstFun(); // OK

                void fun() const

                // pA_->nonConstFun(); // compilation error

                ;






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 1 hour ago

























                answered 2 hours ago









                bolov

                28.1k664121




                28.1k664121



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52607625%2fwhy-is-constness-not-enforced-for-pointers%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Comments

                    Popular posts from this blog

                    What does second last employer means? [closed]

                    List of Gilmore Girls characters

                    Confectionery