Function overload for string literals lvalue and rvalue referenceWhy are string literals l-value while all other literals are r-value?What are rvalues, lvalues, xvalues, glvalues, and prvalues?Overload resolution with ref-qualifiersUnexpected overload resolution in visual studio involving void*, string and const char[]C++ how to pass class method to a function that asks a reference to callableOverloaded operator ambiguity on Clang but not on GCC, which one is correct?Is MSVC right to find this method call ambiguous, whilst Clang/GCC don't?Cannot initialize const int from unpacked tupleWhy do my SFINAE expressions no longer work with GCC 8.2?Rvalue reference overload difference between clang and gccResolution of function overloading about initializer_list

Why did Sofia do this to John's bottle?

How to build an overfitted network in order to increase performances

Can a German employer force mandatory overtime and forbid salary discussion?

Can I re-whip whipped cream?

What does 36.000€ mean?

Centered text and Equations aligned

Retracting Recommendation Letters

Prefix all commands in shell

What are the factors that decide on whether you die instantly or get knocked out in PUBG?

What's the best way to keep cover of a pan slightly opened?

Collection of open problems in Partial differential equations

Who verifies the trust of certificate authorities?

How could pirates reasonably transport dinosaurs in captivity, some of them enormous, across oceans?

How to pay less tax on a high salary?

Thoughts on using user stories to define business/platform needs?

Infinite series that strangely converge?

Why does std::atomic constructor behave different in C++14 and C++17

Can two moons have intersecting orbits yet be guaranteed not to collide?

Did the Windows 95 screensavers use hardware acceleration APIs?

Why do cargo airlines frequently choose passenger aircraft rather than aircraft designed specifically for cargo?

What is the purpose of the rules in counterpoint composition?

Propagator of a real scalar field does not give an unambiguous result

Did the Mueller report find that Trump committed any felonies?

How to create "wave"-like type in Illustrator



Function overload for string literals lvalue and rvalue reference


Why are string literals l-value while all other literals are r-value?What are rvalues, lvalues, xvalues, glvalues, and prvalues?Overload resolution with ref-qualifiersUnexpected overload resolution in visual studio involving void*, string and const char[]C++ how to pass class method to a function that asks a reference to callableOverloaded operator ambiguity on Clang but not on GCC, which one is correct?Is MSVC right to find this method call ambiguous, whilst Clang/GCC don't?Cannot initialize const int from unpacked tupleWhy do my SFINAE expressions no longer work with GCC 8.2?Rvalue reference overload difference between clang and gccResolution of function overloading about initializer_list






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









16


















The function test below is overloaded for lvalue empty strings, lvalue non-empty strings and rvalue strings. I tried to compile with Clang and GCC but in both case I do not have the result I expected.



#include <iostream>

void test(const char (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;

template <unsigned long int N>
void test(const char (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;

void test(char*&&) std::cout << __PRETTY_FUNCTION__ << std::endl;

int main()
char str1[] = "";
char str2[] = "test";
test("");
test("test");
test(str1);
test(str2);



Output with clang version 6.0.0-1ubuntu2:



clang++ test.cpp -o test.out && ./test.out
void test(const char (&)[1])
void test(const char (&)[N]) [N = 5]
void test(char *&&)
void test(char *&&)


Output with g++ (MinGW.org GCC-8.2.0-3):



g++ test.cpp -o test.exe && test.exe
test.cpp: In function 'int main()':
test.cpp:15:11: error: call of overloaded 'test(char [1])' is ambiguous
test(str1);
^
test.cpp:3:6: note: candidate: 'void test(const char (&)[1])'
void test(const char (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
^~~~
test.cpp:6:6: note: candidate: 'void test(const char (&)[N]) [with long unsigned int N = 1]'
void test(const char (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
^~~~
test.cpp:8:6: note: candidate: 'void test(char*&&)'
void test(char*&&) std::cout << __PRETTY_FUNCTION__ << std::endl;
^~~~


My questions are:



  1. Which compiler is correct?

  2. With Clang, why test(str1) and test(str2) choose the rvalue overload while they are lvalues?

  3. With GCC, why the call test(str1) is ambiguous?

  4. Is there a standard rule for this situation?

  5. How to fix the two last calls?

Thank you.










share|improve this question

































    16


















    The function test below is overloaded for lvalue empty strings, lvalue non-empty strings and rvalue strings. I tried to compile with Clang and GCC but in both case I do not have the result I expected.



    #include <iostream>

    void test(const char (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;

    template <unsigned long int N>
    void test(const char (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;

    void test(char*&&) std::cout << __PRETTY_FUNCTION__ << std::endl;

    int main()
    char str1[] = "";
    char str2[] = "test";
    test("");
    test("test");
    test(str1);
    test(str2);



    Output with clang version 6.0.0-1ubuntu2:



    clang++ test.cpp -o test.out && ./test.out
    void test(const char (&)[1])
    void test(const char (&)[N]) [N = 5]
    void test(char *&&)
    void test(char *&&)


    Output with g++ (MinGW.org GCC-8.2.0-3):



    g++ test.cpp -o test.exe && test.exe
    test.cpp: In function 'int main()':
    test.cpp:15:11: error: call of overloaded 'test(char [1])' is ambiguous
    test(str1);
    ^
    test.cpp:3:6: note: candidate: 'void test(const char (&)[1])'
    void test(const char (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
    ^~~~
    test.cpp:6:6: note: candidate: 'void test(const char (&)[N]) [with long unsigned int N = 1]'
    void test(const char (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
    ^~~~
    test.cpp:8:6: note: candidate: 'void test(char*&&)'
    void test(char*&&) std::cout << __PRETTY_FUNCTION__ << std::endl;
    ^~~~


    My questions are:



    1. Which compiler is correct?

    2. With Clang, why test(str1) and test(str2) choose the rvalue overload while they are lvalues?

    3. With GCC, why the call test(str1) is ambiguous?

    4. Is there a standard rule for this situation?

    5. How to fix the two last calls?

    Thank you.










    share|improve this question





























      16













      16









      16


      1






      The function test below is overloaded for lvalue empty strings, lvalue non-empty strings and rvalue strings. I tried to compile with Clang and GCC but in both case I do not have the result I expected.



      #include <iostream>

      void test(const char (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;

      template <unsigned long int N>
      void test(const char (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;

      void test(char*&&) std::cout << __PRETTY_FUNCTION__ << std::endl;

      int main()
      char str1[] = "";
      char str2[] = "test";
      test("");
      test("test");
      test(str1);
      test(str2);



      Output with clang version 6.0.0-1ubuntu2:



      clang++ test.cpp -o test.out && ./test.out
      void test(const char (&)[1])
      void test(const char (&)[N]) [N = 5]
      void test(char *&&)
      void test(char *&&)


      Output with g++ (MinGW.org GCC-8.2.0-3):



      g++ test.cpp -o test.exe && test.exe
      test.cpp: In function 'int main()':
      test.cpp:15:11: error: call of overloaded 'test(char [1])' is ambiguous
      test(str1);
      ^
      test.cpp:3:6: note: candidate: 'void test(const char (&)[1])'
      void test(const char (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
      ^~~~
      test.cpp:6:6: note: candidate: 'void test(const char (&)[N]) [with long unsigned int N = 1]'
      void test(const char (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
      ^~~~
      test.cpp:8:6: note: candidate: 'void test(char*&&)'
      void test(char*&&) std::cout << __PRETTY_FUNCTION__ << std::endl;
      ^~~~


      My questions are:



      1. Which compiler is correct?

      2. With Clang, why test(str1) and test(str2) choose the rvalue overload while they are lvalues?

      3. With GCC, why the call test(str1) is ambiguous?

      4. Is there a standard rule for this situation?

      5. How to fix the two last calls?

      Thank you.










      share|improve this question
















      The function test below is overloaded for lvalue empty strings, lvalue non-empty strings and rvalue strings. I tried to compile with Clang and GCC but in both case I do not have the result I expected.



      #include <iostream>

      void test(const char (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;

      template <unsigned long int N>
      void test(const char (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;

      void test(char*&&) std::cout << __PRETTY_FUNCTION__ << std::endl;

      int main()
      char str1[] = "";
      char str2[] = "test";
      test("");
      test("test");
      test(str1);
      test(str2);



      Output with clang version 6.0.0-1ubuntu2:



      clang++ test.cpp -o test.out && ./test.out
      void test(const char (&)[1])
      void test(const char (&)[N]) [N = 5]
      void test(char *&&)
      void test(char *&&)


      Output with g++ (MinGW.org GCC-8.2.0-3):



      g++ test.cpp -o test.exe && test.exe
      test.cpp: In function 'int main()':
      test.cpp:15:11: error: call of overloaded 'test(char [1])' is ambiguous
      test(str1);
      ^
      test.cpp:3:6: note: candidate: 'void test(const char (&)[1])'
      void test(const char (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
      ^~~~
      test.cpp:6:6: note: candidate: 'void test(const char (&)[N]) [with long unsigned int N = 1]'
      void test(const char (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
      ^~~~
      test.cpp:8:6: note: candidate: 'void test(char*&&)'
      void test(char*&&) std::cout << __PRETTY_FUNCTION__ << std::endl;
      ^~~~


      My questions are:



      1. Which compiler is correct?

      2. With Clang, why test(str1) and test(str2) choose the rvalue overload while they are lvalues?

      3. With GCC, why the call test(str1) is ambiguous?

      4. Is there a standard rule for this situation?

      5. How to fix the two last calls?

      Thank you.







      c++ language-lawyer overload-resolution value-categories






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 27 at 11:34









      L. F.

      11.3k5 gold badges25 silver badges52 bronze badges




      11.3k5 gold badges25 silver badges52 bronze badges










      asked Sep 27 at 10:53









      BaptistouBaptistou

      60211 bronze badges




      60211 bronze badges

























          3 Answers
          3






          active

          oldest

          votes


















          13




















          1. Which compiler is correct ?



          GCC is correct.




          1. With clang, why str1 and str2 choose the rvalue overload while they are lvalues ?



          Clang is wrong on test(str1);, it should be ambiguous. For test(str2);, str2 could convert to pointer implicitly, i.e. the array-to-pointer decay. The converted char* is an rvalue. For the same reason as #3, the implicit conversion sequences have the same ranking, then non-template function is prefered; test(char*&&) is selected.




          1. With gcc, why call with str1 is ambiguous ?



          For test(const char (&)[1]) to be called, qualification conversion from char[1] to const char[1] is required; for test(char*&&) to be called, array-to-pointer conversion is required. Both are qualified as exact match and have the same ranking.




          1. Is there a standard rule for this situation ?



          See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.




          1. How to fix the two last calls ?



          It depends on your intent.






          share|improve this answer


































            3



















            String literals are not rvalues. (→)




            1. How to fix the two last calls?



            You can disambiguate everything with template specializations:



            #include <iostream>

            template<typename C, std::size_t N>
            void test(const C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
            template<typename C>
            void test(const C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
            template<typename C, std::size_t N>
            void test(const C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
            template<typename C>
            void test(const C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
            template<typename C, std::size_t N>
            void test(C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
            template<typename C>
            void test(C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
            template<typename C, std::size_t N>
            void test(C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
            template<typename C>
            void test(C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;

            int main()
            char str1[] = "";
            char str2[] = "test";
            test("");
            test("test");
            test(str1);
            test(str2);
            test(std::move(str1));
            test(std::move(str2));
            const char str3[] = "";
            const char str4[] = "test";
            test(std::move(str3));
            test(std::move(str4));



            gives




            void test(const C (&)[1]) [with C = char]

            void test(const C (&)[N]) [with C = char; long unsigned int N = 5]

            void test(C (&)[1]) [with C = char]

            void test(C (&)[N]) [with C = char; long unsigned int N = 5]

            void test(C (&&)[1]) [with C = char]

            void test(C (&&)[N]) [with C = char; long unsigned int N = 5]

            void test(const C (&&)[1]) [with C = char]

            void test(const C (&&)[N]) [with C = char; long unsigned int N = 5]







            share|improve this answer


































              1



















              Thank you @songyuanyao for your answer, I understand now why test(char*&&) is chosen in the two last cases. I was able to remove ambiguity with template specialization on first overload thanks to @Darklighter answer too.



              So I solved my problem such as below :



              #include <iostream>

              template <unsigned long int N>
              void test(const char (&)[N])
              std::cout << __PRETTY_FUNCTION__ << " //non-empty literal" << std::endl;


              template <>
              void test(const char (&)[1])
              std::cout << __PRETTY_FUNCTION__ << " //empty literal" << std::endl;


              void test(char*&&)
              std::cout << __PRETTY_FUNCTION__ << " //string variable" << std::endl;


              int main()
              char str1[] = "";
              char str2[] = "test";
              test("");
              test("test");
              test(str1);
              test(str2);



              Output :



              clang++ test.cpp -o test.out && ./test.out
              void test(const char (&)[1]) //empty literal
              void test(const char (&)[N]) [N = 5] //non-empty literal
              void test(char *&&) //string variable
              void test(char *&&) //string variable

              g++ test.cpp -o test.exe && test.exe
              void test(const char (&)[N]) [with long unsigned int N = 1] //empty literal
              void test(const char (&)[N]) [with long unsigned int N = 5] //non-empty literal
              void test(char*&&) //string variable
              void test(char*&&) //string variable





              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',
                autoActivateHeartbeat: false,
                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/4.0/"u003ecc by-sa 4.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%2f58133084%2ffunction-overload-for-string-literals-lvalue-and-rvalue-reference%23new-answer', 'question_page');

                );

                Post as a guest















                Required, but never shown


























                3 Answers
                3






                active

                oldest

                votes








                3 Answers
                3






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                13




















                1. Which compiler is correct ?



                GCC is correct.




                1. With clang, why str1 and str2 choose the rvalue overload while they are lvalues ?



                Clang is wrong on test(str1);, it should be ambiguous. For test(str2);, str2 could convert to pointer implicitly, i.e. the array-to-pointer decay. The converted char* is an rvalue. For the same reason as #3, the implicit conversion sequences have the same ranking, then non-template function is prefered; test(char*&&) is selected.




                1. With gcc, why call with str1 is ambiguous ?



                For test(const char (&)[1]) to be called, qualification conversion from char[1] to const char[1] is required; for test(char*&&) to be called, array-to-pointer conversion is required. Both are qualified as exact match and have the same ranking.




                1. Is there a standard rule for this situation ?



                See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.




                1. How to fix the two last calls ?



                It depends on your intent.






                share|improve this answer































                  13




















                  1. Which compiler is correct ?



                  GCC is correct.




                  1. With clang, why str1 and str2 choose the rvalue overload while they are lvalues ?



                  Clang is wrong on test(str1);, it should be ambiguous. For test(str2);, str2 could convert to pointer implicitly, i.e. the array-to-pointer decay. The converted char* is an rvalue. For the same reason as #3, the implicit conversion sequences have the same ranking, then non-template function is prefered; test(char*&&) is selected.




                  1. With gcc, why call with str1 is ambiguous ?



                  For test(const char (&)[1]) to be called, qualification conversion from char[1] to const char[1] is required; for test(char*&&) to be called, array-to-pointer conversion is required. Both are qualified as exact match and have the same ranking.




                  1. Is there a standard rule for this situation ?



                  See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.




                  1. How to fix the two last calls ?



                  It depends on your intent.






                  share|improve this answer





























                    13















                    13











                    13










                    1. Which compiler is correct ?



                    GCC is correct.




                    1. With clang, why str1 and str2 choose the rvalue overload while they are lvalues ?



                    Clang is wrong on test(str1);, it should be ambiguous. For test(str2);, str2 could convert to pointer implicitly, i.e. the array-to-pointer decay. The converted char* is an rvalue. For the same reason as #3, the implicit conversion sequences have the same ranking, then non-template function is prefered; test(char*&&) is selected.




                    1. With gcc, why call with str1 is ambiguous ?



                    For test(const char (&)[1]) to be called, qualification conversion from char[1] to const char[1] is required; for test(char*&&) to be called, array-to-pointer conversion is required. Both are qualified as exact match and have the same ranking.




                    1. Is there a standard rule for this situation ?



                    See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.




                    1. How to fix the two last calls ?



                    It depends on your intent.






                    share|improve this answer

















                    1. Which compiler is correct ?



                    GCC is correct.




                    1. With clang, why str1 and str2 choose the rvalue overload while they are lvalues ?



                    Clang is wrong on test(str1);, it should be ambiguous. For test(str2);, str2 could convert to pointer implicitly, i.e. the array-to-pointer decay. The converted char* is an rvalue. For the same reason as #3, the implicit conversion sequences have the same ranking, then non-template function is prefered; test(char*&&) is selected.




                    1. With gcc, why call with str1 is ambiguous ?



                    For test(const char (&)[1]) to be called, qualification conversion from char[1] to const char[1] is required; for test(char*&&) to be called, array-to-pointer conversion is required. Both are qualified as exact match and have the same ranking.




                    1. Is there a standard rule for this situation ?



                    See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.




                    1. How to fix the two last calls ?



                    It depends on your intent.







                    share|improve this answer















                    share|improve this answer




                    share|improve this answer








                    edited Sep 28 at 8:25

























                    answered Sep 27 at 11:28









                    songyuanyaosongyuanyao

                    112k13 gold badges214 silver badges291 bronze badges




                    112k13 gold badges214 silver badges291 bronze badges


























                        3



















                        String literals are not rvalues. (→)




                        1. How to fix the two last calls?



                        You can disambiguate everything with template specializations:



                        #include <iostream>

                        template<typename C, std::size_t N>
                        void test(const C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                        template<typename C>
                        void test(const C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                        template<typename C, std::size_t N>
                        void test(const C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                        template<typename C>
                        void test(const C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                        template<typename C, std::size_t N>
                        void test(C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                        template<typename C>
                        void test(C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                        template<typename C, std::size_t N>
                        void test(C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                        template<typename C>
                        void test(C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;

                        int main()
                        char str1[] = "";
                        char str2[] = "test";
                        test("");
                        test("test");
                        test(str1);
                        test(str2);
                        test(std::move(str1));
                        test(std::move(str2));
                        const char str3[] = "";
                        const char str4[] = "test";
                        test(std::move(str3));
                        test(std::move(str4));



                        gives




                        void test(const C (&)[1]) [with C = char]

                        void test(const C (&)[N]) [with C = char; long unsigned int N = 5]

                        void test(C (&)[1]) [with C = char]

                        void test(C (&)[N]) [with C = char; long unsigned int N = 5]

                        void test(C (&&)[1]) [with C = char]

                        void test(C (&&)[N]) [with C = char; long unsigned int N = 5]

                        void test(const C (&&)[1]) [with C = char]

                        void test(const C (&&)[N]) [with C = char; long unsigned int N = 5]







                        share|improve this answer































                          3



















                          String literals are not rvalues. (→)




                          1. How to fix the two last calls?



                          You can disambiguate everything with template specializations:



                          #include <iostream>

                          template<typename C, std::size_t N>
                          void test(const C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                          template<typename C>
                          void test(const C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                          template<typename C, std::size_t N>
                          void test(const C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                          template<typename C>
                          void test(const C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                          template<typename C, std::size_t N>
                          void test(C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                          template<typename C>
                          void test(C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                          template<typename C, std::size_t N>
                          void test(C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                          template<typename C>
                          void test(C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;

                          int main()
                          char str1[] = "";
                          char str2[] = "test";
                          test("");
                          test("test");
                          test(str1);
                          test(str2);
                          test(std::move(str1));
                          test(std::move(str2));
                          const char str3[] = "";
                          const char str4[] = "test";
                          test(std::move(str3));
                          test(std::move(str4));



                          gives




                          void test(const C (&)[1]) [with C = char]

                          void test(const C (&)[N]) [with C = char; long unsigned int N = 5]

                          void test(C (&)[1]) [with C = char]

                          void test(C (&)[N]) [with C = char; long unsigned int N = 5]

                          void test(C (&&)[1]) [with C = char]

                          void test(C (&&)[N]) [with C = char; long unsigned int N = 5]

                          void test(const C (&&)[1]) [with C = char]

                          void test(const C (&&)[N]) [with C = char; long unsigned int N = 5]







                          share|improve this answer





























                            3















                            3











                            3









                            String literals are not rvalues. (→)




                            1. How to fix the two last calls?



                            You can disambiguate everything with template specializations:



                            #include <iostream>

                            template<typename C, std::size_t N>
                            void test(const C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C>
                            void test(const C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C, std::size_t N>
                            void test(const C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C>
                            void test(const C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C, std::size_t N>
                            void test(C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C>
                            void test(C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C, std::size_t N>
                            void test(C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C>
                            void test(C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;

                            int main()
                            char str1[] = "";
                            char str2[] = "test";
                            test("");
                            test("test");
                            test(str1);
                            test(str2);
                            test(std::move(str1));
                            test(std::move(str2));
                            const char str3[] = "";
                            const char str4[] = "test";
                            test(std::move(str3));
                            test(std::move(str4));



                            gives




                            void test(const C (&)[1]) [with C = char]

                            void test(const C (&)[N]) [with C = char; long unsigned int N = 5]

                            void test(C (&)[1]) [with C = char]

                            void test(C (&)[N]) [with C = char; long unsigned int N = 5]

                            void test(C (&&)[1]) [with C = char]

                            void test(C (&&)[N]) [with C = char; long unsigned int N = 5]

                            void test(const C (&&)[1]) [with C = char]

                            void test(const C (&&)[N]) [with C = char; long unsigned int N = 5]







                            share|improve this answer
















                            String literals are not rvalues. (→)




                            1. How to fix the two last calls?



                            You can disambiguate everything with template specializations:



                            #include <iostream>

                            template<typename C, std::size_t N>
                            void test(const C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C>
                            void test(const C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C, std::size_t N>
                            void test(const C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C>
                            void test(const C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C, std::size_t N>
                            void test(C (&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C>
                            void test(C (&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C, std::size_t N>
                            void test(C (&&)[N]) std::cout << __PRETTY_FUNCTION__ << std::endl;
                            template<typename C>
                            void test(C (&&)[1]) std::cout << __PRETTY_FUNCTION__ << std::endl;

                            int main()
                            char str1[] = "";
                            char str2[] = "test";
                            test("");
                            test("test");
                            test(str1);
                            test(str2);
                            test(std::move(str1));
                            test(std::move(str2));
                            const char str3[] = "";
                            const char str4[] = "test";
                            test(std::move(str3));
                            test(std::move(str4));



                            gives




                            void test(const C (&)[1]) [with C = char]

                            void test(const C (&)[N]) [with C = char; long unsigned int N = 5]

                            void test(C (&)[1]) [with C = char]

                            void test(C (&)[N]) [with C = char; long unsigned int N = 5]

                            void test(C (&&)[1]) [with C = char]

                            void test(C (&&)[N]) [with C = char; long unsigned int N = 5]

                            void test(const C (&&)[1]) [with C = char]

                            void test(const C (&&)[N]) [with C = char; long unsigned int N = 5]








                            share|improve this answer















                            share|improve this answer




                            share|improve this answer








                            edited Sep 27 at 18:59

























                            answered Sep 27 at 11:03









                            DarklighterDarklighter

                            1,7341 gold badge10 silver badges20 bronze badges




                            1,7341 gold badge10 silver badges20 bronze badges
























                                1



















                                Thank you @songyuanyao for your answer, I understand now why test(char*&&) is chosen in the two last cases. I was able to remove ambiguity with template specialization on first overload thanks to @Darklighter answer too.



                                So I solved my problem such as below :



                                #include <iostream>

                                template <unsigned long int N>
                                void test(const char (&)[N])
                                std::cout << __PRETTY_FUNCTION__ << " //non-empty literal" << std::endl;


                                template <>
                                void test(const char (&)[1])
                                std::cout << __PRETTY_FUNCTION__ << " //empty literal" << std::endl;


                                void test(char*&&)
                                std::cout << __PRETTY_FUNCTION__ << " //string variable" << std::endl;


                                int main()
                                char str1[] = "";
                                char str2[] = "test";
                                test("");
                                test("test");
                                test(str1);
                                test(str2);



                                Output :



                                clang++ test.cpp -o test.out && ./test.out
                                void test(const char (&)[1]) //empty literal
                                void test(const char (&)[N]) [N = 5] //non-empty literal
                                void test(char *&&) //string variable
                                void test(char *&&) //string variable

                                g++ test.cpp -o test.exe && test.exe
                                void test(const char (&)[N]) [with long unsigned int N = 1] //empty literal
                                void test(const char (&)[N]) [with long unsigned int N = 5] //non-empty literal
                                void test(char*&&) //string variable
                                void test(char*&&) //string variable





                                share|improve this answer





























                                  1



















                                  Thank you @songyuanyao for your answer, I understand now why test(char*&&) is chosen in the two last cases. I was able to remove ambiguity with template specialization on first overload thanks to @Darklighter answer too.



                                  So I solved my problem such as below :



                                  #include <iostream>

                                  template <unsigned long int N>
                                  void test(const char (&)[N])
                                  std::cout << __PRETTY_FUNCTION__ << " //non-empty literal" << std::endl;


                                  template <>
                                  void test(const char (&)[1])
                                  std::cout << __PRETTY_FUNCTION__ << " //empty literal" << std::endl;


                                  void test(char*&&)
                                  std::cout << __PRETTY_FUNCTION__ << " //string variable" << std::endl;


                                  int main()
                                  char str1[] = "";
                                  char str2[] = "test";
                                  test("");
                                  test("test");
                                  test(str1);
                                  test(str2);



                                  Output :



                                  clang++ test.cpp -o test.out && ./test.out
                                  void test(const char (&)[1]) //empty literal
                                  void test(const char (&)[N]) [N = 5] //non-empty literal
                                  void test(char *&&) //string variable
                                  void test(char *&&) //string variable

                                  g++ test.cpp -o test.exe && test.exe
                                  void test(const char (&)[N]) [with long unsigned int N = 1] //empty literal
                                  void test(const char (&)[N]) [with long unsigned int N = 5] //non-empty literal
                                  void test(char*&&) //string variable
                                  void test(char*&&) //string variable





                                  share|improve this answer



























                                    1















                                    1











                                    1









                                    Thank you @songyuanyao for your answer, I understand now why test(char*&&) is chosen in the two last cases. I was able to remove ambiguity with template specialization on first overload thanks to @Darklighter answer too.



                                    So I solved my problem such as below :



                                    #include <iostream>

                                    template <unsigned long int N>
                                    void test(const char (&)[N])
                                    std::cout << __PRETTY_FUNCTION__ << " //non-empty literal" << std::endl;


                                    template <>
                                    void test(const char (&)[1])
                                    std::cout << __PRETTY_FUNCTION__ << " //empty literal" << std::endl;


                                    void test(char*&&)
                                    std::cout << __PRETTY_FUNCTION__ << " //string variable" << std::endl;


                                    int main()
                                    char str1[] = "";
                                    char str2[] = "test";
                                    test("");
                                    test("test");
                                    test(str1);
                                    test(str2);



                                    Output :



                                    clang++ test.cpp -o test.out && ./test.out
                                    void test(const char (&)[1]) //empty literal
                                    void test(const char (&)[N]) [N = 5] //non-empty literal
                                    void test(char *&&) //string variable
                                    void test(char *&&) //string variable

                                    g++ test.cpp -o test.exe && test.exe
                                    void test(const char (&)[N]) [with long unsigned int N = 1] //empty literal
                                    void test(const char (&)[N]) [with long unsigned int N = 5] //non-empty literal
                                    void test(char*&&) //string variable
                                    void test(char*&&) //string variable





                                    share|improve this answer














                                    Thank you @songyuanyao for your answer, I understand now why test(char*&&) is chosen in the two last cases. I was able to remove ambiguity with template specialization on first overload thanks to @Darklighter answer too.



                                    So I solved my problem such as below :



                                    #include <iostream>

                                    template <unsigned long int N>
                                    void test(const char (&)[N])
                                    std::cout << __PRETTY_FUNCTION__ << " //non-empty literal" << std::endl;


                                    template <>
                                    void test(const char (&)[1])
                                    std::cout << __PRETTY_FUNCTION__ << " //empty literal" << std::endl;


                                    void test(char*&&)
                                    std::cout << __PRETTY_FUNCTION__ << " //string variable" << std::endl;


                                    int main()
                                    char str1[] = "";
                                    char str2[] = "test";
                                    test("");
                                    test("test");
                                    test(str1);
                                    test(str2);



                                    Output :



                                    clang++ test.cpp -o test.out && ./test.out
                                    void test(const char (&)[1]) //empty literal
                                    void test(const char (&)[N]) [N = 5] //non-empty literal
                                    void test(char *&&) //string variable
                                    void test(char *&&) //string variable

                                    g++ test.cpp -o test.exe && test.exe
                                    void test(const char (&)[N]) [with long unsigned int N = 1] //empty literal
                                    void test(const char (&)[N]) [with long unsigned int N = 5] //non-empty literal
                                    void test(char*&&) //string variable
                                    void test(char*&&) //string variable






                                    share|improve this answer













                                    share|improve this answer




                                    share|improve this answer










                                    answered Sep 30 at 10:30









                                    BaptistouBaptistou

                                    60211 bronze badges




                                    60211 bronze badges































                                        draft saved

                                        draft discarded















































                                        Thanks for contributing an answer to Stack Overflow!


                                        • Please be sure to answer the question. Provide details and share your research!

                                        But avoid


                                        • Asking for help, clarification, or responding to other answers.

                                        • Making statements based on opinion; back them up with references or personal experience.

                                        To learn more, see our tips on writing great answers.




                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function ()
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f58133084%2ffunction-overload-for-string-literals-lvalue-and-rvalue-reference%23new-answer', 'question_page');

                                        );

                                        Post as a guest















                                        Required, but never shown





















































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown

































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown









                                        Popular posts from this blog

                                        Tamil (spriik) Luke uk diar | Nawigatjuun

                                        Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

                                        Where does the image of a data connector as a sharp metal spike originate from?Where does the concept of infected people turning into zombies only after death originate from?Where does the motif of a reanimated human head originate?Where did the notion that Dragons could speak originate?Where does the archetypal image of the 'Grey' alien come from?Where did the suffix '-Man' originate?Where does the notion of being injured or killed by an illusion originate?Where did the term “sophont” originate?Where does the trope of magic spells being driven by advanced technology originate from?Where did the term “the living impaired” originate?