Reputation: 13826
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
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 “cv2T2
” 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
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