2

I have a function which accepts a std::string&:

void f(std::string& s) { ... }

I have a const char* which should be the input parameter for that function. This works:

const char* s1 = "test";
std::string s2{s};
f(s2);

This doesn't:

const char* s1 = "test";
f({s1});

Why isn't this possible? The funny thing is that CLion IDE is not complaining, but the compiler is:

no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘std::basic_string<char>&’
6
  • 3
    Why would you expect it to work? Commented Oct 24, 2016 at 19:24
  • 1
    The function expects a string by reference, and your second option is not doing that. In your first example though, s1 is completely unneeded given your example: std::string s2 = "test"; Commented Oct 24, 2016 at 19:29
  • 1
    The funny thing is that CLion IDE is not complaining, but the compiler is: -- CLIon is not a compiler. Compiler wins. Commented Oct 24, 2016 at 19:30
  • 2
    If you think about it const char* is not a std::string so for it to even work at all a new temporary string would need to be created to pass to the function. But the function modifies the string you pass in!! So it won't accept a temporary. Non-const reference won't bind to temporaries. Commented Oct 24, 2016 at 19:31
  • 1
    If you need a non-const reference, you cannot pass a temporary anyway. Commented Oct 24, 2016 at 19:31

3 Answers 3

5

This has nothing to do with constructing std::string from char const*.

f expects a lvalue to a string, and by creating a temporary instance on the spot, you're providing an rvalue, which cannot be bound to a non-const lvalue reference. f(string{}) is just as invalid.

Sign up to request clarification or add additional context in comments.

7 Comments

Well, f expects an lvalue. Using an lvalue reference parameter is the way you express that in C++, but that doesn't meant hat that "f expects a reference".
@KerrekSB I'm not sure I understand. I thought that the function expects a lvalue reference, and if you pass a lvalue the reference is bound to it.
You can't really "expect a reference". Functions are called with arguments, arguments are expressions, and expressions are never references. What matters is that the expression is an lvalue. References are a way to talk about lvalues.
@KerrekSB Okay, I changed the wording, is it better now? I will have to educate myself about this.
Mm, not really. Values don't "refer" to anything. The simple matter of the fact is that "f expects an lvalue of std::string", or maybe "a string lvalue". I don't know any better or simpler way of saying that. An lvalue is just a particular kind of value.
|
1

Your function receives a non const reference and you are passing a temporary object, which requires a copy or a const reference parameter. Two solutions, creating another function to receive the object as a rvalue reference and call the other overload within

void f(string&& s) {  f(s); } 

to allow temporary objects as parameter, or change your function definition to receive any object but as a constant reference

void f(const std::string& s) { ... }

Comments

0

One option is to change your function to take a string by value, not by reference. Then it will work. In any case, in C++11 sometimes it's preferable to pass by value, not by reference.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.