fluter
fluter

Reputation: 13826

why initialize reference succeeds with one constructor but not the other

Our code was using something like below, to pass a const string reference:

const char* str = // passed in;
const std::string& sym(str);

Then I need to fix it for take symbol only as the first 5 chars, I did:

const std::string& sym(str, 5);

but this throws me this compiling error:

error: expression list treated as compound expression in initializer [-fpermissive]

Why can I invoke the first constructor, but no the second one?

Upvotes: 1

Views: 62

Answers (2)

Daniel Langr
Daniel Langr

Reputation: 23527

Check the documentation for initialization of references [dcl.init.ref/5]:

A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows..

In your case

const std::string& sym(str, 5);    

the expression is a coumpound expression str, 5. Basically, it's the same as if you wrote

const std::string& sym = (str, 5);    

Which, in both cases, boils down to...

const std::string& sym = 5;

or

const std::string& sym(5);

My understanding is that the Standard allows initializing a reference only by a single expression, not by a pair of expressions separated by a comma.

And, there is no matching constructor (which says the second error in your Godbolt demo).

As a solution, you can write:

const std::string& sym{str, 5};

since, according to [dcl.init/17.1]:

If the initializer is a (non-parenthesized) braced-init-list or is = braced-init-list, the object or reference is list-initialized.

Upvotes: 1

HolyBlackCat
HolyBlackCat

Reputation: 96699

Because the language doesn't allow that.

The (...) here don't invoke constructors of std::string, because the type of your variable is not an std::string, but a reference. Instead, T &ref(x); is just a different way to write T &ref = x;.

Note that in const std::string& sym(str);, since the type of str is const char * rather than a std::string, a temporary std::string is constructed and bound to the reference, and its lifetime is extended.

This makes const std::string& sym(str); mostly equivalent to const std::string sym(str); (but slightly more confusing).

Upvotes: 1

Related Questions