Why can const char* const & = “hello” compile?

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











up vote
41
down vote

favorite
7












I am reading a code snippet from a book and find this:



const char* const & a = "hello"; //can compile 
const char*& a = "hello"; //cannot


All I know is that when initializing a reference, the array to pointer conversion would not take place.



const char* const &, a reference to a const pointer, the pointer points to const char.



const char*&, a reference to a pointer, the pointer points to
const char.



So why does adding an extra const, indicating that the pointer is a const, allow it to compile?







share|improve this question


























    up vote
    41
    down vote

    favorite
    7












    I am reading a code snippet from a book and find this:



    const char* const & a = "hello"; //can compile 
    const char*& a = "hello"; //cannot


    All I know is that when initializing a reference, the array to pointer conversion would not take place.



    const char* const &, a reference to a const pointer, the pointer points to const char.



    const char*&, a reference to a pointer, the pointer points to
    const char.



    So why does adding an extra const, indicating that the pointer is a const, allow it to compile?







    share|improve this question
























      up vote
      41
      down vote

      favorite
      7









      up vote
      41
      down vote

      favorite
      7






      7





      I am reading a code snippet from a book and find this:



      const char* const & a = "hello"; //can compile 
      const char*& a = "hello"; //cannot


      All I know is that when initializing a reference, the array to pointer conversion would not take place.



      const char* const &, a reference to a const pointer, the pointer points to const char.



      const char*&, a reference to a pointer, the pointer points to
      const char.



      So why does adding an extra const, indicating that the pointer is a const, allow it to compile?







      share|improve this question














      I am reading a code snippet from a book and find this:



      const char* const & a = "hello"; //can compile 
      const char*& a = "hello"; //cannot


      All I know is that when initializing a reference, the array to pointer conversion would not take place.



      const char* const &, a reference to a const pointer, the pointer points to const char.



      const char*&, a reference to a pointer, the pointer points to
      const char.



      So why does adding an extra const, indicating that the pointer is a const, allow it to compile?









      share|improve this question













      share|improve this question




      share|improve this question








      edited Aug 27 at 15:23









      Boann

      35.6k1184116




      35.6k1184116










      asked Aug 27 at 4:39









      Rick

      1,309724




      1,309724






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          34
          down vote



          accepted










          It's essentially adhering to this formula



          T const & a = something_convertible_to_T;


          Where T is const char*. In the first case, a temporary pointer can be materialized, assigned the address of the literal, and then have itself bound to the reference. In the second case, since the lvalue reference isn't const, it can't happen. Another example of more of the same



          const char* && a = "hello"; // rvalue ref makes a no into a yes.


          Now the temporary pointer is bound to an rvalue reference.






          share|improve this answer


















          • 5




            Yes I get it know. It's the same reason as for const int& a = 3; //yes, int&a = 3; //no. The formula is very helpful. Thanks. It merely becomes harder to recognize that when comes to pointer.
            – Rick
            Aug 27 at 5:03











          • @SkepticalEmpiricist - It is. What's important to consider when taking in that comment is that the identity conversion also counts (though it's obviously not a very interesting case). const int& a = 3; materializes a temporary from a literal int prvalue, and binds a reference to it.
            – StoryTeller
            Aug 27 at 7:34










          • @StoryTeller I still cannot fully follow, I thought I know what the identity conversion means in The Standard but I cannot put it into use trying to understand what you're saying. Can I kindly ask you to elaborate on this?
            – SkepticalEmpiricist
            Aug 27 at 7:44






          • 1




            @SkepticalEmpiricist - I wasn't trying to be as exact as the standard is on this, but my line of thought (and explanation) tries to follow the C++17 changes to prvalues, the temporary materialization conversion and this bit about initializing references.
            – StoryTeller
            Aug 27 at 7:50











          • @SkepticalEmpiricist - It's simpler than that. The temporary can be materialized in all the examples. It's just that the whole of [dcl.init.ref]/5 doesn't define the meaning of such an initialization. So the program is ill-formed.
            – StoryTeller
            Aug 27 at 8:17

















          up vote
          6
          down vote













          Some additional phrasing for the bored, after reading the superb answer by StoryTeller, as I had to go through a different thought process about this.



          So syntactically, In both lines we define a reference a, and in both we shall have a materialization of a temporary pointer that takes the address of the string literal. The only difference between the two is the 2nd const appearing only here:



          const char* const & a = "hello";


          and not here:



          const char*& a = "hello";


          This 2nd const denotes that the object being referenced here, a pointer in this case, is itself const, as in it cannot be modified using this reference.



          Hence, because the type of this string literal is const char[6] (and not const char * for example), our lvalue reference to type const char* in the second line cannot bind to it -- but the reference in the first line, being a reference to type const char* const could. Why? Because of the rules of reference initialization:




          [A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows: ...]



          cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2




          As in, our T in this quoted text is const char*, and only in the first line it is cv-qualified no less than our object. i.e. const char[6] has the semantics of a const pointer, as opposed to just pointer to const.



          The Clang error for the second line, read with that in mind, tells us exactly this:



          error: non-const lvalue reference to type 'const char *' cannot bind to a value of unrelated type 'const char [6]'
          const char*& a = "hello";
          ^ ~~~~~~~


          The part about being non-const lvalue reference is exactly that -- the lvalue in our case is a pointer to const, but itself isn't const! Unlike the first line.



          For this exact reason, this can compiles error-free:



          char* const & a = "hello";


          ISO C++11 warning aside, a compiler lets this one pass (not that it should, as the string literal is a 'const char [6]' and we shouldn't be dropping this first const), as the reference is now const with regards to its object, the pointer.



          Another interesting thing is that An rvalue reference const char* && a (no "2nd const") could bind to the temporary pointer that has materialized from the string literal, as StoryTeller provided himself. Why is that? Because of the rules of array to pointer conversion:




          An lvalue or rvalue of type "array of N T" or "array of unknown bound
          of T" can be converted to a prvalue of type "pointer to T".




          No mention of const or other cv-qualification phrasing in here, but this stands only as long as we're initializing an rvalue ref.






          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%2f52032645%2fwhy-can-const-char-const-hello-compile%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
            34
            down vote



            accepted










            It's essentially adhering to this formula



            T const & a = something_convertible_to_T;


            Where T is const char*. In the first case, a temporary pointer can be materialized, assigned the address of the literal, and then have itself bound to the reference. In the second case, since the lvalue reference isn't const, it can't happen. Another example of more of the same



            const char* && a = "hello"; // rvalue ref makes a no into a yes.


            Now the temporary pointer is bound to an rvalue reference.






            share|improve this answer


















            • 5




              Yes I get it know. It's the same reason as for const int& a = 3; //yes, int&a = 3; //no. The formula is very helpful. Thanks. It merely becomes harder to recognize that when comes to pointer.
              – Rick
              Aug 27 at 5:03











            • @SkepticalEmpiricist - It is. What's important to consider when taking in that comment is that the identity conversion also counts (though it's obviously not a very interesting case). const int& a = 3; materializes a temporary from a literal int prvalue, and binds a reference to it.
              – StoryTeller
              Aug 27 at 7:34










            • @StoryTeller I still cannot fully follow, I thought I know what the identity conversion means in The Standard but I cannot put it into use trying to understand what you're saying. Can I kindly ask you to elaborate on this?
              – SkepticalEmpiricist
              Aug 27 at 7:44






            • 1




              @SkepticalEmpiricist - I wasn't trying to be as exact as the standard is on this, but my line of thought (and explanation) tries to follow the C++17 changes to prvalues, the temporary materialization conversion and this bit about initializing references.
              – StoryTeller
              Aug 27 at 7:50











            • @SkepticalEmpiricist - It's simpler than that. The temporary can be materialized in all the examples. It's just that the whole of [dcl.init.ref]/5 doesn't define the meaning of such an initialization. So the program is ill-formed.
              – StoryTeller
              Aug 27 at 8:17














            up vote
            34
            down vote



            accepted










            It's essentially adhering to this formula



            T const & a = something_convertible_to_T;


            Where T is const char*. In the first case, a temporary pointer can be materialized, assigned the address of the literal, and then have itself bound to the reference. In the second case, since the lvalue reference isn't const, it can't happen. Another example of more of the same



            const char* && a = "hello"; // rvalue ref makes a no into a yes.


            Now the temporary pointer is bound to an rvalue reference.






            share|improve this answer


















            • 5




              Yes I get it know. It's the same reason as for const int& a = 3; //yes, int&a = 3; //no. The formula is very helpful. Thanks. It merely becomes harder to recognize that when comes to pointer.
              – Rick
              Aug 27 at 5:03











            • @SkepticalEmpiricist - It is. What's important to consider when taking in that comment is that the identity conversion also counts (though it's obviously not a very interesting case). const int& a = 3; materializes a temporary from a literal int prvalue, and binds a reference to it.
              – StoryTeller
              Aug 27 at 7:34










            • @StoryTeller I still cannot fully follow, I thought I know what the identity conversion means in The Standard but I cannot put it into use trying to understand what you're saying. Can I kindly ask you to elaborate on this?
              – SkepticalEmpiricist
              Aug 27 at 7:44






            • 1




              @SkepticalEmpiricist - I wasn't trying to be as exact as the standard is on this, but my line of thought (and explanation) tries to follow the C++17 changes to prvalues, the temporary materialization conversion and this bit about initializing references.
              – StoryTeller
              Aug 27 at 7:50











            • @SkepticalEmpiricist - It's simpler than that. The temporary can be materialized in all the examples. It's just that the whole of [dcl.init.ref]/5 doesn't define the meaning of such an initialization. So the program is ill-formed.
              – StoryTeller
              Aug 27 at 8:17












            up vote
            34
            down vote



            accepted







            up vote
            34
            down vote



            accepted






            It's essentially adhering to this formula



            T const & a = something_convertible_to_T;


            Where T is const char*. In the first case, a temporary pointer can be materialized, assigned the address of the literal, and then have itself bound to the reference. In the second case, since the lvalue reference isn't const, it can't happen. Another example of more of the same



            const char* && a = "hello"; // rvalue ref makes a no into a yes.


            Now the temporary pointer is bound to an rvalue reference.






            share|improve this answer














            It's essentially adhering to this formula



            T const & a = something_convertible_to_T;


            Where T is const char*. In the first case, a temporary pointer can be materialized, assigned the address of the literal, and then have itself bound to the reference. In the second case, since the lvalue reference isn't const, it can't happen. Another example of more of the same



            const char* && a = "hello"; // rvalue ref makes a no into a yes.


            Now the temporary pointer is bound to an rvalue reference.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Aug 27 at 5:03

























            answered Aug 27 at 4:42









            StoryTeller

            82.4k12163228




            82.4k12163228







            • 5




              Yes I get it know. It's the same reason as for const int& a = 3; //yes, int&a = 3; //no. The formula is very helpful. Thanks. It merely becomes harder to recognize that when comes to pointer.
              – Rick
              Aug 27 at 5:03











            • @SkepticalEmpiricist - It is. What's important to consider when taking in that comment is that the identity conversion also counts (though it's obviously not a very interesting case). const int& a = 3; materializes a temporary from a literal int prvalue, and binds a reference to it.
              – StoryTeller
              Aug 27 at 7:34










            • @StoryTeller I still cannot fully follow, I thought I know what the identity conversion means in The Standard but I cannot put it into use trying to understand what you're saying. Can I kindly ask you to elaborate on this?
              – SkepticalEmpiricist
              Aug 27 at 7:44






            • 1




              @SkepticalEmpiricist - I wasn't trying to be as exact as the standard is on this, but my line of thought (and explanation) tries to follow the C++17 changes to prvalues, the temporary materialization conversion and this bit about initializing references.
              – StoryTeller
              Aug 27 at 7:50











            • @SkepticalEmpiricist - It's simpler than that. The temporary can be materialized in all the examples. It's just that the whole of [dcl.init.ref]/5 doesn't define the meaning of such an initialization. So the program is ill-formed.
              – StoryTeller
              Aug 27 at 8:17












            • 5




              Yes I get it know. It's the same reason as for const int& a = 3; //yes, int&a = 3; //no. The formula is very helpful. Thanks. It merely becomes harder to recognize that when comes to pointer.
              – Rick
              Aug 27 at 5:03











            • @SkepticalEmpiricist - It is. What's important to consider when taking in that comment is that the identity conversion also counts (though it's obviously not a very interesting case). const int& a = 3; materializes a temporary from a literal int prvalue, and binds a reference to it.
              – StoryTeller
              Aug 27 at 7:34










            • @StoryTeller I still cannot fully follow, I thought I know what the identity conversion means in The Standard but I cannot put it into use trying to understand what you're saying. Can I kindly ask you to elaborate on this?
              – SkepticalEmpiricist
              Aug 27 at 7:44






            • 1




              @SkepticalEmpiricist - I wasn't trying to be as exact as the standard is on this, but my line of thought (and explanation) tries to follow the C++17 changes to prvalues, the temporary materialization conversion and this bit about initializing references.
              – StoryTeller
              Aug 27 at 7:50











            • @SkepticalEmpiricist - It's simpler than that. The temporary can be materialized in all the examples. It's just that the whole of [dcl.init.ref]/5 doesn't define the meaning of such an initialization. So the program is ill-formed.
              – StoryTeller
              Aug 27 at 8:17







            5




            5




            Yes I get it know. It's the same reason as for const int& a = 3; //yes, int&a = 3; //no. The formula is very helpful. Thanks. It merely becomes harder to recognize that when comes to pointer.
            – Rick
            Aug 27 at 5:03





            Yes I get it know. It's the same reason as for const int& a = 3; //yes, int&a = 3; //no. The formula is very helpful. Thanks. It merely becomes harder to recognize that when comes to pointer.
            – Rick
            Aug 27 at 5:03













            @SkepticalEmpiricist - It is. What's important to consider when taking in that comment is that the identity conversion also counts (though it's obviously not a very interesting case). const int& a = 3; materializes a temporary from a literal int prvalue, and binds a reference to it.
            – StoryTeller
            Aug 27 at 7:34




            @SkepticalEmpiricist - It is. What's important to consider when taking in that comment is that the identity conversion also counts (though it's obviously not a very interesting case). const int& a = 3; materializes a temporary from a literal int prvalue, and binds a reference to it.
            – StoryTeller
            Aug 27 at 7:34












            @StoryTeller I still cannot fully follow, I thought I know what the identity conversion means in The Standard but I cannot put it into use trying to understand what you're saying. Can I kindly ask you to elaborate on this?
            – SkepticalEmpiricist
            Aug 27 at 7:44




            @StoryTeller I still cannot fully follow, I thought I know what the identity conversion means in The Standard but I cannot put it into use trying to understand what you're saying. Can I kindly ask you to elaborate on this?
            – SkepticalEmpiricist
            Aug 27 at 7:44




            1




            1




            @SkepticalEmpiricist - I wasn't trying to be as exact as the standard is on this, but my line of thought (and explanation) tries to follow the C++17 changes to prvalues, the temporary materialization conversion and this bit about initializing references.
            – StoryTeller
            Aug 27 at 7:50





            @SkepticalEmpiricist - I wasn't trying to be as exact as the standard is on this, but my line of thought (and explanation) tries to follow the C++17 changes to prvalues, the temporary materialization conversion and this bit about initializing references.
            – StoryTeller
            Aug 27 at 7:50













            @SkepticalEmpiricist - It's simpler than that. The temporary can be materialized in all the examples. It's just that the whole of [dcl.init.ref]/5 doesn't define the meaning of such an initialization. So the program is ill-formed.
            – StoryTeller
            Aug 27 at 8:17




            @SkepticalEmpiricist - It's simpler than that. The temporary can be materialized in all the examples. It's just that the whole of [dcl.init.ref]/5 doesn't define the meaning of such an initialization. So the program is ill-formed.
            – StoryTeller
            Aug 27 at 8:17












            up vote
            6
            down vote













            Some additional phrasing for the bored, after reading the superb answer by StoryTeller, as I had to go through a different thought process about this.



            So syntactically, In both lines we define a reference a, and in both we shall have a materialization of a temporary pointer that takes the address of the string literal. The only difference between the two is the 2nd const appearing only here:



            const char* const & a = "hello";


            and not here:



            const char*& a = "hello";


            This 2nd const denotes that the object being referenced here, a pointer in this case, is itself const, as in it cannot be modified using this reference.



            Hence, because the type of this string literal is const char[6] (and not const char * for example), our lvalue reference to type const char* in the second line cannot bind to it -- but the reference in the first line, being a reference to type const char* const could. Why? Because of the rules of reference initialization:




            [A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows: ...]



            cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2




            As in, our T in this quoted text is const char*, and only in the first line it is cv-qualified no less than our object. i.e. const char[6] has the semantics of a const pointer, as opposed to just pointer to const.



            The Clang error for the second line, read with that in mind, tells us exactly this:



            error: non-const lvalue reference to type 'const char *' cannot bind to a value of unrelated type 'const char [6]'
            const char*& a = "hello";
            ^ ~~~~~~~


            The part about being non-const lvalue reference is exactly that -- the lvalue in our case is a pointer to const, but itself isn't const! Unlike the first line.



            For this exact reason, this can compiles error-free:



            char* const & a = "hello";


            ISO C++11 warning aside, a compiler lets this one pass (not that it should, as the string literal is a 'const char [6]' and we shouldn't be dropping this first const), as the reference is now const with regards to its object, the pointer.



            Another interesting thing is that An rvalue reference const char* && a (no "2nd const") could bind to the temporary pointer that has materialized from the string literal, as StoryTeller provided himself. Why is that? Because of the rules of array to pointer conversion:




            An lvalue or rvalue of type "array of N T" or "array of unknown bound
            of T" can be converted to a prvalue of type "pointer to T".




            No mention of const or other cv-qualification phrasing in here, but this stands only as long as we're initializing an rvalue ref.






            share|improve this answer


























              up vote
              6
              down vote













              Some additional phrasing for the bored, after reading the superb answer by StoryTeller, as I had to go through a different thought process about this.



              So syntactically, In both lines we define a reference a, and in both we shall have a materialization of a temporary pointer that takes the address of the string literal. The only difference between the two is the 2nd const appearing only here:



              const char* const & a = "hello";


              and not here:



              const char*& a = "hello";


              This 2nd const denotes that the object being referenced here, a pointer in this case, is itself const, as in it cannot be modified using this reference.



              Hence, because the type of this string literal is const char[6] (and not const char * for example), our lvalue reference to type const char* in the second line cannot bind to it -- but the reference in the first line, being a reference to type const char* const could. Why? Because of the rules of reference initialization:




              [A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows: ...]



              cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2




              As in, our T in this quoted text is const char*, and only in the first line it is cv-qualified no less than our object. i.e. const char[6] has the semantics of a const pointer, as opposed to just pointer to const.



              The Clang error for the second line, read with that in mind, tells us exactly this:



              error: non-const lvalue reference to type 'const char *' cannot bind to a value of unrelated type 'const char [6]'
              const char*& a = "hello";
              ^ ~~~~~~~


              The part about being non-const lvalue reference is exactly that -- the lvalue in our case is a pointer to const, but itself isn't const! Unlike the first line.



              For this exact reason, this can compiles error-free:



              char* const & a = "hello";


              ISO C++11 warning aside, a compiler lets this one pass (not that it should, as the string literal is a 'const char [6]' and we shouldn't be dropping this first const), as the reference is now const with regards to its object, the pointer.



              Another interesting thing is that An rvalue reference const char* && a (no "2nd const") could bind to the temporary pointer that has materialized from the string literal, as StoryTeller provided himself. Why is that? Because of the rules of array to pointer conversion:




              An lvalue or rvalue of type "array of N T" or "array of unknown bound
              of T" can be converted to a prvalue of type "pointer to T".




              No mention of const or other cv-qualification phrasing in here, but this stands only as long as we're initializing an rvalue ref.






              share|improve this answer
























                up vote
                6
                down vote










                up vote
                6
                down vote









                Some additional phrasing for the bored, after reading the superb answer by StoryTeller, as I had to go through a different thought process about this.



                So syntactically, In both lines we define a reference a, and in both we shall have a materialization of a temporary pointer that takes the address of the string literal. The only difference between the two is the 2nd const appearing only here:



                const char* const & a = "hello";


                and not here:



                const char*& a = "hello";


                This 2nd const denotes that the object being referenced here, a pointer in this case, is itself const, as in it cannot be modified using this reference.



                Hence, because the type of this string literal is const char[6] (and not const char * for example), our lvalue reference to type const char* in the second line cannot bind to it -- but the reference in the first line, being a reference to type const char* const could. Why? Because of the rules of reference initialization:




                [A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows: ...]



                cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2




                As in, our T in this quoted text is const char*, and only in the first line it is cv-qualified no less than our object. i.e. const char[6] has the semantics of a const pointer, as opposed to just pointer to const.



                The Clang error for the second line, read with that in mind, tells us exactly this:



                error: non-const lvalue reference to type 'const char *' cannot bind to a value of unrelated type 'const char [6]'
                const char*& a = "hello";
                ^ ~~~~~~~


                The part about being non-const lvalue reference is exactly that -- the lvalue in our case is a pointer to const, but itself isn't const! Unlike the first line.



                For this exact reason, this can compiles error-free:



                char* const & a = "hello";


                ISO C++11 warning aside, a compiler lets this one pass (not that it should, as the string literal is a 'const char [6]' and we shouldn't be dropping this first const), as the reference is now const with regards to its object, the pointer.



                Another interesting thing is that An rvalue reference const char* && a (no "2nd const") could bind to the temporary pointer that has materialized from the string literal, as StoryTeller provided himself. Why is that? Because of the rules of array to pointer conversion:




                An lvalue or rvalue of type "array of N T" or "array of unknown bound
                of T" can be converted to a prvalue of type "pointer to T".




                No mention of const or other cv-qualification phrasing in here, but this stands only as long as we're initializing an rvalue ref.






                share|improve this answer














                Some additional phrasing for the bored, after reading the superb answer by StoryTeller, as I had to go through a different thought process about this.



                So syntactically, In both lines we define a reference a, and in both we shall have a materialization of a temporary pointer that takes the address of the string literal. The only difference between the two is the 2nd const appearing only here:



                const char* const & a = "hello";


                and not here:



                const char*& a = "hello";


                This 2nd const denotes that the object being referenced here, a pointer in this case, is itself const, as in it cannot be modified using this reference.



                Hence, because the type of this string literal is const char[6] (and not const char * for example), our lvalue reference to type const char* in the second line cannot bind to it -- but the reference in the first line, being a reference to type const char* const could. Why? Because of the rules of reference initialization:




                [A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows: ...]



                cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2




                As in, our T in this quoted text is const char*, and only in the first line it is cv-qualified no less than our object. i.e. const char[6] has the semantics of a const pointer, as opposed to just pointer to const.



                The Clang error for the second line, read with that in mind, tells us exactly this:



                error: non-const lvalue reference to type 'const char *' cannot bind to a value of unrelated type 'const char [6]'
                const char*& a = "hello";
                ^ ~~~~~~~


                The part about being non-const lvalue reference is exactly that -- the lvalue in our case is a pointer to const, but itself isn't const! Unlike the first line.



                For this exact reason, this can compiles error-free:



                char* const & a = "hello";


                ISO C++11 warning aside, a compiler lets this one pass (not that it should, as the string literal is a 'const char [6]' and we shouldn't be dropping this first const), as the reference is now const with regards to its object, the pointer.



                Another interesting thing is that An rvalue reference const char* && a (no "2nd const") could bind to the temporary pointer that has materialized from the string literal, as StoryTeller provided himself. Why is that? Because of the rules of array to pointer conversion:




                An lvalue or rvalue of type "array of N T" or "array of unknown bound
                of T" can be converted to a prvalue of type "pointer to T".




                No mention of const or other cv-qualification phrasing in here, but this stands only as long as we're initializing an rvalue ref.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 1 hour ago

























                answered Aug 27 at 4:55









                SkepticalEmpiricist

                2,591720




                2,591720



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52032645%2fwhy-can-const-char-const-hello-compile%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