Standard behavior for direct initialization of unsigned short

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











up vote
16
down vote

favorite












I noticed today that in the example code:



void print(unsigned short a) 
std::cout << a << std::endl;



Initialization and use works like this:



print(short (5));


But not like this:



print(unsigned short(6));



main.cpp:16:8: error: expected primary-expression before 'unsigned'
print(unsigned short(6));




And it's not to do with the type since this also works:



typedef unsigned short ushort;
print(ushort (6));


Live example.



So I went searching for what the standard says about value initialization. It turns out nothing:




The effects of value initialization are:



1) if T is a class type ...



2) if T is a non-union class type ...



2) if T is a class type ...



3) if T is an array type, ..



4) otherwise, the object is zero-initialized.




Modifications made for readability. Original source.



What are the rules about value initialization of POD types? What is the reason that unsigned qualified types can't be value initialized? Is this more to do with the fact they are rvalues?










share|improve this question



























    up vote
    16
    down vote

    favorite












    I noticed today that in the example code:



    void print(unsigned short a) 
    std::cout << a << std::endl;



    Initialization and use works like this:



    print(short (5));


    But not like this:



    print(unsigned short(6));



    main.cpp:16:8: error: expected primary-expression before 'unsigned'
    print(unsigned short(6));




    And it's not to do with the type since this also works:



    typedef unsigned short ushort;
    print(ushort (6));


    Live example.



    So I went searching for what the standard says about value initialization. It turns out nothing:




    The effects of value initialization are:



    1) if T is a class type ...



    2) if T is a non-union class type ...



    2) if T is a class type ...



    3) if T is an array type, ..



    4) otherwise, the object is zero-initialized.




    Modifications made for readability. Original source.



    What are the rules about value initialization of POD types? What is the reason that unsigned qualified types can't be value initialized? Is this more to do with the fact they are rvalues?










    share|improve this question

























      up vote
      16
      down vote

      favorite









      up vote
      16
      down vote

      favorite











      I noticed today that in the example code:



      void print(unsigned short a) 
      std::cout << a << std::endl;



      Initialization and use works like this:



      print(short (5));


      But not like this:



      print(unsigned short(6));



      main.cpp:16:8: error: expected primary-expression before 'unsigned'
      print(unsigned short(6));




      And it's not to do with the type since this also works:



      typedef unsigned short ushort;
      print(ushort (6));


      Live example.



      So I went searching for what the standard says about value initialization. It turns out nothing:




      The effects of value initialization are:



      1) if T is a class type ...



      2) if T is a non-union class type ...



      2) if T is a class type ...



      3) if T is an array type, ..



      4) otherwise, the object is zero-initialized.




      Modifications made for readability. Original source.



      What are the rules about value initialization of POD types? What is the reason that unsigned qualified types can't be value initialized? Is this more to do with the fact they are rvalues?










      share|improve this question















      I noticed today that in the example code:



      void print(unsigned short a) 
      std::cout << a << std::endl;



      Initialization and use works like this:



      print(short (5));


      But not like this:



      print(unsigned short(6));



      main.cpp:16:8: error: expected primary-expression before 'unsigned'
      print(unsigned short(6));




      And it's not to do with the type since this also works:



      typedef unsigned short ushort;
      print(ushort (6));


      Live example.



      So I went searching for what the standard says about value initialization. It turns out nothing:




      The effects of value initialization are:



      1) if T is a class type ...



      2) if T is a non-union class type ...



      2) if T is a class type ...



      3) if T is an array type, ..



      4) otherwise, the object is zero-initialized.




      Modifications made for readability. Original source.



      What are the rules about value initialization of POD types? What is the reason that unsigned qualified types can't be value initialized? Is this more to do with the fact they are rvalues?







      c++ syntax casting initialization language-lawyer






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 10 at 10:53









      songyuanyao

      85k9163222




      85k9163222










      asked Aug 17 at 10:58









      Fantastic Mr Fox

      17.4k1765125




      17.4k1765125






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          21
          down vote



          accepted











          What is the reason that unsigned qualified types can't be value initialized?




          It's just because only single-word type name could be used in functional cast expression, while unsigned short is not a single-word type name; short is.




          The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name: unsigned int(expression) or int*(expression) are not valid), followed by a single expression in parentheses.




          As you showed, you can use typedef as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6), or (unsigned short)6.



          From the standard, §7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:




          A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.




          And simple-type-specifier:




          simple-type-specifier:
          nested-name-specifier opt
          type-name
          nested-name-specifier template simple-template-id
          nested-name-specifier opt
          template-name
          char
          char16_t
          char32_t
          wchar_t
          bool
          short
          int
          long
          signed
          unsigned
          float
          double
          void
          auto
          decltype-specifier
          type-name:
          class-name
          enum-name
          typedef-name
          simple-template-id
          decltype-specifier:
          decltype ( expression )
          decltype ( auto )



          typename-specifier:




          typename-specifier:
          typename nested-name-specifier identifier
          typename nested-name-specifier template opt
          simple-template-id






          share|improve this answer






















          • Ahh, ok, its not even value initialization. Makes sense. Good answer.
            – Fantastic Mr Fox
            Aug 17 at 11:06










          • A Follow up question which is heavily related is why in value initialization does not cover other types. In this expression unsigned int i(6) is it value initialized, or zero initialized?
            – Fantastic Mr Fox
            Aug 17 at 11:10






          • 1




            Note that (unsigned short)(), i.e., trying to use value initialisation does not work. (unsigned short) does work, though.
            – Dietmar Kühl
            Aug 17 at 11:12






          • 2




            @FantasticMrFox unsigned int i(6) is direct initialization. i is initialized to 6.
            – songyuanyao
            Aug 17 at 11:12










          • @songyuanyao I obviously have some work to do learning initialization names.
            – Fantastic Mr Fox
            Aug 17 at 11:15

















          up vote
          7
          down vote













          That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work



          template <typename T> void use(T);
          int main()
          use(unsigned int());
          use(const int());
          use(long long());



          The work-around is to use an alias for the respective type instead, i.e., all of these do work:



          template <typename T> void use(T);
          int main()
          using type = unsigned int; use(type());
          using type = const int; use(type());
          using type = long long; use(type());



          Parenthesis can also be used for value initialisation although the require the use of curlies:



          template <typename T> void use(T);
          int main()
          use((unsigned int));
          use((const int));
          use((long long));






          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%2f51893895%2fstandard-behavior-for-direct-initialization-of-unsigned-short%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
            21
            down vote



            accepted











            What is the reason that unsigned qualified types can't be value initialized?




            It's just because only single-word type name could be used in functional cast expression, while unsigned short is not a single-word type name; short is.




            The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name: unsigned int(expression) or int*(expression) are not valid), followed by a single expression in parentheses.




            As you showed, you can use typedef as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6), or (unsigned short)6.



            From the standard, §7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:




            A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.




            And simple-type-specifier:




            simple-type-specifier:
            nested-name-specifier opt
            type-name
            nested-name-specifier template simple-template-id
            nested-name-specifier opt
            template-name
            char
            char16_t
            char32_t
            wchar_t
            bool
            short
            int
            long
            signed
            unsigned
            float
            double
            void
            auto
            decltype-specifier
            type-name:
            class-name
            enum-name
            typedef-name
            simple-template-id
            decltype-specifier:
            decltype ( expression )
            decltype ( auto )



            typename-specifier:




            typename-specifier:
            typename nested-name-specifier identifier
            typename nested-name-specifier template opt
            simple-template-id






            share|improve this answer






















            • Ahh, ok, its not even value initialization. Makes sense. Good answer.
              – Fantastic Mr Fox
              Aug 17 at 11:06










            • A Follow up question which is heavily related is why in value initialization does not cover other types. In this expression unsigned int i(6) is it value initialized, or zero initialized?
              – Fantastic Mr Fox
              Aug 17 at 11:10






            • 1




              Note that (unsigned short)(), i.e., trying to use value initialisation does not work. (unsigned short) does work, though.
              – Dietmar Kühl
              Aug 17 at 11:12






            • 2




              @FantasticMrFox unsigned int i(6) is direct initialization. i is initialized to 6.
              – songyuanyao
              Aug 17 at 11:12










            • @songyuanyao I obviously have some work to do learning initialization names.
              – Fantastic Mr Fox
              Aug 17 at 11:15














            up vote
            21
            down vote



            accepted











            What is the reason that unsigned qualified types can't be value initialized?




            It's just because only single-word type name could be used in functional cast expression, while unsigned short is not a single-word type name; short is.




            The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name: unsigned int(expression) or int*(expression) are not valid), followed by a single expression in parentheses.




            As you showed, you can use typedef as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6), or (unsigned short)6.



            From the standard, §7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:




            A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.




            And simple-type-specifier:




            simple-type-specifier:
            nested-name-specifier opt
            type-name
            nested-name-specifier template simple-template-id
            nested-name-specifier opt
            template-name
            char
            char16_t
            char32_t
            wchar_t
            bool
            short
            int
            long
            signed
            unsigned
            float
            double
            void
            auto
            decltype-specifier
            type-name:
            class-name
            enum-name
            typedef-name
            simple-template-id
            decltype-specifier:
            decltype ( expression )
            decltype ( auto )



            typename-specifier:




            typename-specifier:
            typename nested-name-specifier identifier
            typename nested-name-specifier template opt
            simple-template-id






            share|improve this answer






















            • Ahh, ok, its not even value initialization. Makes sense. Good answer.
              – Fantastic Mr Fox
              Aug 17 at 11:06










            • A Follow up question which is heavily related is why in value initialization does not cover other types. In this expression unsigned int i(6) is it value initialized, or zero initialized?
              – Fantastic Mr Fox
              Aug 17 at 11:10






            • 1




              Note that (unsigned short)(), i.e., trying to use value initialisation does not work. (unsigned short) does work, though.
              – Dietmar Kühl
              Aug 17 at 11:12






            • 2




              @FantasticMrFox unsigned int i(6) is direct initialization. i is initialized to 6.
              – songyuanyao
              Aug 17 at 11:12










            • @songyuanyao I obviously have some work to do learning initialization names.
              – Fantastic Mr Fox
              Aug 17 at 11:15












            up vote
            21
            down vote



            accepted







            up vote
            21
            down vote



            accepted







            What is the reason that unsigned qualified types can't be value initialized?




            It's just because only single-word type name could be used in functional cast expression, while unsigned short is not a single-word type name; short is.




            The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name: unsigned int(expression) or int*(expression) are not valid), followed by a single expression in parentheses.




            As you showed, you can use typedef as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6), or (unsigned short)6.



            From the standard, §7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:




            A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.




            And simple-type-specifier:




            simple-type-specifier:
            nested-name-specifier opt
            type-name
            nested-name-specifier template simple-template-id
            nested-name-specifier opt
            template-name
            char
            char16_t
            char32_t
            wchar_t
            bool
            short
            int
            long
            signed
            unsigned
            float
            double
            void
            auto
            decltype-specifier
            type-name:
            class-name
            enum-name
            typedef-name
            simple-template-id
            decltype-specifier:
            decltype ( expression )
            decltype ( auto )



            typename-specifier:




            typename-specifier:
            typename nested-name-specifier identifier
            typename nested-name-specifier template opt
            simple-template-id






            share|improve this answer















            What is the reason that unsigned qualified types can't be value initialized?




            It's just because only single-word type name could be used in functional cast expression, while unsigned short is not a single-word type name; short is.




            The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name: unsigned int(expression) or int*(expression) are not valid), followed by a single expression in parentheses.




            As you showed, you can use typedef as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6), or (unsigned short)6.



            From the standard, §7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:




            A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.




            And simple-type-specifier:




            simple-type-specifier:
            nested-name-specifier opt
            type-name
            nested-name-specifier template simple-template-id
            nested-name-specifier opt
            template-name
            char
            char16_t
            char32_t
            wchar_t
            bool
            short
            int
            long
            signed
            unsigned
            float
            double
            void
            auto
            decltype-specifier
            type-name:
            class-name
            enum-name
            typedef-name
            simple-template-id
            decltype-specifier:
            decltype ( expression )
            decltype ( auto )



            typename-specifier:




            typename-specifier:
            typename nested-name-specifier identifier
            typename nested-name-specifier template opt
            simple-template-id







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Aug 17 at 11:32

























            answered Aug 17 at 11:04









            songyuanyao

            85k9163222




            85k9163222











            • Ahh, ok, its not even value initialization. Makes sense. Good answer.
              – Fantastic Mr Fox
              Aug 17 at 11:06










            • A Follow up question which is heavily related is why in value initialization does not cover other types. In this expression unsigned int i(6) is it value initialized, or zero initialized?
              – Fantastic Mr Fox
              Aug 17 at 11:10






            • 1




              Note that (unsigned short)(), i.e., trying to use value initialisation does not work. (unsigned short) does work, though.
              – Dietmar Kühl
              Aug 17 at 11:12






            • 2




              @FantasticMrFox unsigned int i(6) is direct initialization. i is initialized to 6.
              – songyuanyao
              Aug 17 at 11:12










            • @songyuanyao I obviously have some work to do learning initialization names.
              – Fantastic Mr Fox
              Aug 17 at 11:15
















            • Ahh, ok, its not even value initialization. Makes sense. Good answer.
              – Fantastic Mr Fox
              Aug 17 at 11:06










            • A Follow up question which is heavily related is why in value initialization does not cover other types. In this expression unsigned int i(6) is it value initialized, or zero initialized?
              – Fantastic Mr Fox
              Aug 17 at 11:10






            • 1




              Note that (unsigned short)(), i.e., trying to use value initialisation does not work. (unsigned short) does work, though.
              – Dietmar Kühl
              Aug 17 at 11:12






            • 2




              @FantasticMrFox unsigned int i(6) is direct initialization. i is initialized to 6.
              – songyuanyao
              Aug 17 at 11:12










            • @songyuanyao I obviously have some work to do learning initialization names.
              – Fantastic Mr Fox
              Aug 17 at 11:15















            Ahh, ok, its not even value initialization. Makes sense. Good answer.
            – Fantastic Mr Fox
            Aug 17 at 11:06




            Ahh, ok, its not even value initialization. Makes sense. Good answer.
            – Fantastic Mr Fox
            Aug 17 at 11:06












            A Follow up question which is heavily related is why in value initialization does not cover other types. In this expression unsigned int i(6) is it value initialized, or zero initialized?
            – Fantastic Mr Fox
            Aug 17 at 11:10




            A Follow up question which is heavily related is why in value initialization does not cover other types. In this expression unsigned int i(6) is it value initialized, or zero initialized?
            – Fantastic Mr Fox
            Aug 17 at 11:10




            1




            1




            Note that (unsigned short)(), i.e., trying to use value initialisation does not work. (unsigned short) does work, though.
            – Dietmar Kühl
            Aug 17 at 11:12




            Note that (unsigned short)(), i.e., trying to use value initialisation does not work. (unsigned short) does work, though.
            – Dietmar Kühl
            Aug 17 at 11:12




            2




            2




            @FantasticMrFox unsigned int i(6) is direct initialization. i is initialized to 6.
            – songyuanyao
            Aug 17 at 11:12




            @FantasticMrFox unsigned int i(6) is direct initialization. i is initialized to 6.
            – songyuanyao
            Aug 17 at 11:12












            @songyuanyao I obviously have some work to do learning initialization names.
            – Fantastic Mr Fox
            Aug 17 at 11:15




            @songyuanyao I obviously have some work to do learning initialization names.
            – Fantastic Mr Fox
            Aug 17 at 11:15












            up vote
            7
            down vote













            That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work



            template <typename T> void use(T);
            int main()
            use(unsigned int());
            use(const int());
            use(long long());



            The work-around is to use an alias for the respective type instead, i.e., all of these do work:



            template <typename T> void use(T);
            int main()
            using type = unsigned int; use(type());
            using type = const int; use(type());
            using type = long long; use(type());



            Parenthesis can also be used for value initialisation although the require the use of curlies:



            template <typename T> void use(T);
            int main()
            use((unsigned int));
            use((const int));
            use((long long));






            share|improve this answer


























              up vote
              7
              down vote













              That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work



              template <typename T> void use(T);
              int main()
              use(unsigned int());
              use(const int());
              use(long long());



              The work-around is to use an alias for the respective type instead, i.e., all of these do work:



              template <typename T> void use(T);
              int main()
              using type = unsigned int; use(type());
              using type = const int; use(type());
              using type = long long; use(type());



              Parenthesis can also be used for value initialisation although the require the use of curlies:



              template <typename T> void use(T);
              int main()
              use((unsigned int));
              use((const int));
              use((long long));






              share|improve this answer
























                up vote
                7
                down vote










                up vote
                7
                down vote









                That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work



                template <typename T> void use(T);
                int main()
                use(unsigned int());
                use(const int());
                use(long long());



                The work-around is to use an alias for the respective type instead, i.e., all of these do work:



                template <typename T> void use(T);
                int main()
                using type = unsigned int; use(type());
                using type = const int; use(type());
                using type = long long; use(type());



                Parenthesis can also be used for value initialisation although the require the use of curlies:



                template <typename T> void use(T);
                int main()
                use((unsigned int));
                use((const int));
                use((long long));






                share|improve this answer














                That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work



                template <typename T> void use(T);
                int main()
                use(unsigned int());
                use(const int());
                use(long long());



                The work-around is to use an alias for the respective type instead, i.e., all of these do work:



                template <typename T> void use(T);
                int main()
                using type = unsigned int; use(type());
                using type = const int; use(type());
                using type = long long; use(type());



                Parenthesis can also be used for value initialisation although the require the use of curlies:



                template <typename T> void use(T);
                int main()
                use((unsigned int));
                use((const int));
                use((long long));







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Aug 17 at 11:14

























                answered Aug 17 at 11:09









                Dietmar Kühl

                123k7146306




                123k7146306



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51893895%2fstandard-behavior-for-direct-initialization-of-unsigned-short%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    How to check contact read email or not when send email to Individual?

                    Displaying single band from multi-band raster using QGIS

                    How many registers does an x86_64 CPU actually have?