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;
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:
- Which compiler is correct?
- With Clang, why
test(str1)
andtest(str2)
choose the rvalue overload while they are lvalues? - With GCC, why the call
test(str1)
is ambiguous? - Is there a standard rule for this situation?
- How to fix the two last calls?
Thank you.
c++ language-lawyer overload-resolution value-categories
add a comment
|
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:
- Which compiler is correct?
- With Clang, why
test(str1)
andtest(str2)
choose the rvalue overload while they are lvalues? - With GCC, why the call
test(str1)
is ambiguous? - Is there a standard rule for this situation?
- How to fix the two last calls?
Thank you.
c++ language-lawyer overload-resolution value-categories
add a comment
|
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:
- Which compiler is correct?
- With Clang, why
test(str1)
andtest(str2)
choose the rvalue overload while they are lvalues? - With GCC, why the call
test(str1)
is ambiguous? - Is there a standard rule for this situation?
- How to fix the two last calls?
Thank you.
c++ language-lawyer overload-resolution value-categories
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:
- Which compiler is correct?
- With Clang, why
test(str1)
andtest(str2)
choose the rvalue overload while they are lvalues? - With GCC, why the call
test(str1)
is ambiguous? - Is there a standard rule for this situation?
- How to fix the two last calls?
Thank you.
c++ language-lawyer overload-resolution value-categories
c++ language-lawyer overload-resolution value-categories
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
add a comment
|
add a comment
|
3 Answers
3
active
oldest
votes
- Which compiler is correct ?
GCC is correct.
- 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.
- 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.
- Is there a standard rule for this situation ?
See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.
- How to fix the two last calls ?
It depends on your intent.
add a comment
|
String literals are not rvalues. (→)
- 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]
add a comment
|
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
add a comment
|
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
- Which compiler is correct ?
GCC is correct.
- 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.
- 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.
- Is there a standard rule for this situation ?
See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.
- How to fix the two last calls ?
It depends on your intent.
add a comment
|
- Which compiler is correct ?
GCC is correct.
- 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.
- 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.
- Is there a standard rule for this situation ?
See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.
- How to fix the two last calls ?
It depends on your intent.
add a comment
|
- Which compiler is correct ?
GCC is correct.
- 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.
- 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.
- Is there a standard rule for this situation ?
See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.
- How to fix the two last calls ?
It depends on your intent.
- Which compiler is correct ?
GCC is correct.
- 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.
- 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.
- Is there a standard rule for this situation ?
See the ranking of implicit conversion sequences in overload resolution, and implicit conversions.
- How to fix the two last calls ?
It depends on your intent.
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
add a comment
|
add a comment
|
String literals are not rvalues. (→)
- 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]
add a comment
|
String literals are not rvalues. (→)
- 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]
add a comment
|
String literals are not rvalues. (→)
- 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]
String literals are not rvalues. (→)
- 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]
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
add a comment
|
add a comment
|
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
add a comment
|
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
add a comment
|
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
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
answered Sep 30 at 10:30
BaptistouBaptistou
60211 bronze badges
60211 bronze badges
add a comment
|
add a comment
|
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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