Why doesn't universal reference apply for arrays?

Multi tool use
Multi tool use








up vote
4
down vote

favorite












#include <type_traits>

template<typename T>
void f(const T&)

static_assert(std::is_array_v<T>); // ok


template<typename T>
void g(T&&)

static_assert(std::is_array_v<T>); // error


int main()

char arr[8];
f(arr); // ok
g(arr); // error



My compiler is clang 7.0 with -std=c++17.



Why doesn't universal reference apply for arrays?










share|improve this question

























    up vote
    4
    down vote

    favorite












    #include <type_traits>

    template<typename T>
    void f(const T&)

    static_assert(std::is_array_v<T>); // ok


    template<typename T>
    void g(T&&)

    static_assert(std::is_array_v<T>); // error


    int main()

    char arr[8];
    f(arr); // ok
    g(arr); // error



    My compiler is clang 7.0 with -std=c++17.



    Why doesn't universal reference apply for arrays?










    share|improve this question























      up vote
      4
      down vote

      favorite









      up vote
      4
      down vote

      favorite











      #include <type_traits>

      template<typename T>
      void f(const T&)

      static_assert(std::is_array_v<T>); // ok


      template<typename T>
      void g(T&&)

      static_assert(std::is_array_v<T>); // error


      int main()

      char arr[8];
      f(arr); // ok
      g(arr); // error



      My compiler is clang 7.0 with -std=c++17.



      Why doesn't universal reference apply for arrays?










      share|improve this question













      #include <type_traits>

      template<typename T>
      void f(const T&)

      static_assert(std::is_array_v<T>); // ok


      template<typename T>
      void g(T&&)

      static_assert(std::is_array_v<T>); // error


      int main()

      char arr[8];
      f(arr); // ok
      g(arr); // error



      My compiler is clang 7.0 with -std=c++17.



      Why doesn't universal reference apply for arrays?







      c++ c++11 standards perfect-forwarding forwarding-reference






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 8 at 10:44









      xmllmx

      13.1k880201




      13.1k880201






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          11
          down vote



          accepted










          First of all, these are officially called "forwarding references", not "universal references".



          Your static_assert fails due to the fact that T is deduced as T& when passing an lvalue to a function taking a "forwarding reference" - this is one of the special rules of "forwarding references" that apply during template argument deduction.



          You can fix your assert by stripping any reference out first:



          static_assert(std::is_array_v<std::remove_cvref_t<T>>); 


          live example on godbolt.org




          std::remove_cvref_t is a bleeding edge C++20 feature - you might want to use std::remove_reference_t instead if your compiler doesn't support it.






          share|improve this answer



























            up vote
            0
            down vote













            The relevant rule here when the template argument deduction takes place is:




            Deduction from a function call

            ...

            4. If P is an rvalue reference to a cv-unqualified template parameter (so-called forwarding reference), and the corresponding function call argument is an lvalue, the type lvalue reference to A is used in place of A for deduction.




            So in your case, arr is being deduced as reference to arr and thus the static_assert fails.






            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: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader:
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              ,
              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%2f53206090%2fwhy-doesnt-universal-reference-apply-for-arrays%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
              11
              down vote



              accepted










              First of all, these are officially called "forwarding references", not "universal references".



              Your static_assert fails due to the fact that T is deduced as T& when passing an lvalue to a function taking a "forwarding reference" - this is one of the special rules of "forwarding references" that apply during template argument deduction.



              You can fix your assert by stripping any reference out first:



              static_assert(std::is_array_v<std::remove_cvref_t<T>>); 


              live example on godbolt.org




              std::remove_cvref_t is a bleeding edge C++20 feature - you might want to use std::remove_reference_t instead if your compiler doesn't support it.






              share|improve this answer
























                up vote
                11
                down vote



                accepted










                First of all, these are officially called "forwarding references", not "universal references".



                Your static_assert fails due to the fact that T is deduced as T& when passing an lvalue to a function taking a "forwarding reference" - this is one of the special rules of "forwarding references" that apply during template argument deduction.



                You can fix your assert by stripping any reference out first:



                static_assert(std::is_array_v<std::remove_cvref_t<T>>); 


                live example on godbolt.org




                std::remove_cvref_t is a bleeding edge C++20 feature - you might want to use std::remove_reference_t instead if your compiler doesn't support it.






                share|improve this answer






















                  up vote
                  11
                  down vote



                  accepted







                  up vote
                  11
                  down vote



                  accepted






                  First of all, these are officially called "forwarding references", not "universal references".



                  Your static_assert fails due to the fact that T is deduced as T& when passing an lvalue to a function taking a "forwarding reference" - this is one of the special rules of "forwarding references" that apply during template argument deduction.



                  You can fix your assert by stripping any reference out first:



                  static_assert(std::is_array_v<std::remove_cvref_t<T>>); 


                  live example on godbolt.org




                  std::remove_cvref_t is a bleeding edge C++20 feature - you might want to use std::remove_reference_t instead if your compiler doesn't support it.






                  share|improve this answer












                  First of all, these are officially called "forwarding references", not "universal references".



                  Your static_assert fails due to the fact that T is deduced as T& when passing an lvalue to a function taking a "forwarding reference" - this is one of the special rules of "forwarding references" that apply during template argument deduction.



                  You can fix your assert by stripping any reference out first:



                  static_assert(std::is_array_v<std::remove_cvref_t<T>>); 


                  live example on godbolt.org




                  std::remove_cvref_t is a bleeding edge C++20 feature - you might want to use std::remove_reference_t instead if your compiler doesn't support it.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 8 at 10:46









                  Vittorio Romeo

                  54.8k16144283




                  54.8k16144283






















                      up vote
                      0
                      down vote













                      The relevant rule here when the template argument deduction takes place is:




                      Deduction from a function call

                      ...

                      4. If P is an rvalue reference to a cv-unqualified template parameter (so-called forwarding reference), and the corresponding function call argument is an lvalue, the type lvalue reference to A is used in place of A for deduction.




                      So in your case, arr is being deduced as reference to arr and thus the static_assert fails.






                      share|improve this answer
























                        up vote
                        0
                        down vote













                        The relevant rule here when the template argument deduction takes place is:




                        Deduction from a function call

                        ...

                        4. If P is an rvalue reference to a cv-unqualified template parameter (so-called forwarding reference), and the corresponding function call argument is an lvalue, the type lvalue reference to A is used in place of A for deduction.




                        So in your case, arr is being deduced as reference to arr and thus the static_assert fails.






                        share|improve this answer






















                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          The relevant rule here when the template argument deduction takes place is:




                          Deduction from a function call

                          ...

                          4. If P is an rvalue reference to a cv-unqualified template parameter (so-called forwarding reference), and the corresponding function call argument is an lvalue, the type lvalue reference to A is used in place of A for deduction.




                          So in your case, arr is being deduced as reference to arr and thus the static_assert fails.






                          share|improve this answer












                          The relevant rule here when the template argument deduction takes place is:




                          Deduction from a function call

                          ...

                          4. If P is an rvalue reference to a cv-unqualified template parameter (so-called forwarding reference), and the corresponding function call argument is an lvalue, the type lvalue reference to A is used in place of A for deduction.




                          So in your case, arr is being deduced as reference to arr and thus the static_assert fails.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 8 at 11:05









                          P.W

                          6,8941437




                          6,8941437



























                               

                              draft saved


                              draft discarded















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53206090%2fwhy-doesnt-universal-reference-apply-for-arrays%23new-answer', 'question_page');

                              );

                              Post as a guest














































































                              iM z4Epsz,sWoinz,9V DwUoos19vFhpHoIPS cYgI8bMWIU5Kp,RNag,ugSS2FX5A9cP7WF18NbsBa
                              fkvc4aTXGl9rJ2qQWmjEreug

                              Popular posts from this blog

                              Old paper Canadian currency

                              𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

                              ữḛḳṊẴ ẋ,Ẩṙ,ỹḛẪẠứụỿṞṦ,Ṉẍừ,ứ Ị,Ḵ,ṏ ṇỪḎḰṰọửḊ ṾḨḮữẑỶṑỗḮṣṉẃ Ữẩụ,ṓ,ḹẕḪḫỞṿḭ ỒṱṨẁṋṜ ḅẈ ṉ ứṀḱṑỒḵ,ḏ,ḊḖỹẊ Ẻḷổ,ṥ ẔḲẪụḣể Ṱ ḭỏựẶ Ồ Ṩ,ẂḿṡḾồ ỗṗṡịṞẤḵṽẃ ṸḒẄẘ,ủẞẵṦṟầṓế