Why doesn't universal reference apply for arrays?









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














































































                              Popular posts from this blog

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

                              Edmonton

                              Crossroads (UK TV series)