Does basic_string class really have copy constructor that takes more than one parameter or is it just constructor?
Asked Answered
M

2

1

I was reading Why would a copy constructor have more than one parameter?.

The accepted answer says that:

The old std::basic_string does have one too:

basic_string(const basic_string& s, 
         size_type pos = 0, size_type n = npos)

But http://www.cplusplus.com/reference/string/basic_string/basic_string/ says that:

basic_string (const basic_string& str, size_type pos, size_type len = npos,
              const allocator_type& alloc = allocator_type());

The above isn't a copy constructor but substring constructor that copies the portion of str that begins at the character position pos and spans len characters.

C++ standard section says that:

A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments

So, Is the accepted answer from that link is incorrect? Is this really basic_string class constructor for sub-string? I've checked prototype for this in C++98, C++11 & C++14 specification on the link & all shows the same.

Muggins answered 6/10, 2015 at 18:20 Comment(18)
@Downvoters: Develop a habit to specify reason for downvotes. Why downvotes?Muggins
@owacoder: Then why cplusplus.com/reference/string/basic_string/basic_string says that it is substring constructor not copy constructor?Muggins
Perhaps to clarify its purpose. Regardless, it is still a copy constructor.Feudatory
@owacoder: I thought it was right. But Brian Bi says quora.com/… that it is not copy constructor.Muggins
@Feudatory I can't find this ctor neither in C++03 nor C++11 nor recent drafts. The ctors I find don't have a default argument for the pos parameter. Also, the basic_string spec does contain a basic_string(const basic_string&) constructor.Ting
Sorry, I was wrong, I didn't read carefully. I'll delete my answer at Quora.Severable
@PravasiMeet "Copy-constructor" has a specific meaning in C++ legalese. That constructor is a copy-construtor because it meets the requirements you quoted. It can also be described as a substring constructor (which is not a C++ standard term) to convey additional meaning related to the extra stuff it can do.Hutner
@Downvoters: Why don't you mention the reason for downvotes?Muggins
@Ting - True, the documentation claims it has no default second parameter, in which case it would not be a copy constructor, but the referenced accepted answer claims it is. Hmm. Who's right?Feudatory
@PravasiMeet - Motivating your downvotes often result in you being called names - "stupid downvoter", or much worse. That soon teaches downvoters to stay anonymous. (And, of course, as I wrote a comment I didn't downvote).Horseflesh
cplusplus.com is not the documentation. It's a third-party website. I have looked into the official ISO/IEC C++ Standard documents (though withdrawn for the C++14 revision of the Standard).Ting
What difference does it make? We are not in the court of law.Cot
@Ting - Sorry for the misnomer. I guess I should have said "a documentation manual says..."Feudatory
@Feudatory apparently that ctor goes back to 1998, old is somewhat of an understatement. This was a good question too bad we did not realize that earlier. It is a lot of unjustified downvotes.Melanesian
@BoPersson it is unfortunate though, sometimes the downvoters are incorrect and often they won't come back to find out.Melanesian
@ShafikYaghmour: Thanks for appreciating my question. This is thing I hate about SO is that many peoples on SO downvotes my question without specify any reason. This question should get more upvotes because it indeed requires research effort. In the past also this was happened with me on SO. This shouldn't really happen.Muggins
You should really be thanking @dyp, the questions dyp asked got to the root of the question and I think we would not have realized it was an interesting question otherwise. Writing a good SO question is very hard, almost every question I ever wrote I ended up with at least 10 revisions before I posted it :-p ... we get so many questions it gets hard not to be jaded after a while. Wish I had better advice.Melanesian
@ShafikYaghmour: The good question remains good whether it is identified as good or not. It is the problem of SO users that they failed to identify that these was good question. (I am not promoting my question) But it also seems that you also haven't upvoted this question In my opinion? Please tell me honestly.Muggins
T
5

The specification of the basic_string class template in the (former) C++11 International Standard [basic.string]p5 contains the following two constructors (among others):

basic_string(const basic_string& str);
// ...
basic_string(const basic_string& str, size_type pos, size_type n = npos,
             const Allocator& a = Allocator());

The first one clearly is a copy constructor, the second one is no copy constructor. Note that there is no constructor in the spec where pos has a default argument.

The situation is essentially the same in C++03, C++14 and C++1z. In C++98, those two constructors have indeed been a single one:

 basic_string(const basic_string& str, size_type pos = 0, size_type n = npos,
 //                                                 ~~~~
              const Allocator& a = Allocator());

But this has been changed to the current version with two separate constructors due to LWG 42.


As far as I know, an implementation of the C++ Standard Library is allowed to merge those two constructors into a single one, which then becomes a copy constructor:

 basic_string(const basic_string& str, size_type pos = 0, size_type n = npos,
 //                                                 ~~~~
              const Allocator& a = Allocator());

This has different behaviour. As explained in LWG 42 (see Shafik Yaghmour's answer), the actual copy ctor of basic_string acquires a copy of str's allocator, whereas the "substring" constructor by default uses a value-initialized new object.

Thanks to Sebastian Redl for pointing that out.

Ting answered 6/10, 2015 at 18:36 Comment(7)
I stand corrected. I overlooked the "no default argument" section. Here, have an upvote.Feudatory
"an implementation of the C++ Standard Library is allowed to merge those two constructors into a single one" This is only because user code can't detect this, right?Severable
@Brian That was my reasoning, yes. I then tried to look up what [conforming] has to say about that case, but I'm not sure that's even covered. There's [member.functions] which does not allow merging but allows splitting; but I'm not sure if it applies to constructors as well.Ting
It looks like back the old specification back in 1998 was indeed similar, too bad we don't have draft standards that go back that far but at least we do have issues and defects.Melanesian
@ShafikYaghmour Thank you. There are some drafts from before 2005, but they're hard to find. I've just looked into some C++98 draft, and it indeed contains the ctor you quote in the DR.Ting
If an implementation were to merge the two constructors, a copy wouldn't copy the source's allocator, it would get the default-constructed one from the defaulted argument.Columbia
@SebastianRedl Ah right, I should have revised my answer after reading Shafik's.Ting
M
3

So the "old", going back to 1998 specification is very similar to one from the original SO answer the OP points to and has changed at least once to what we have today.

The 1998 specification can be found referenced in LWG issue 42: String ctors specify wrong default allocator:

The basic_string<> copy constructor:

basic_string(const basic_string& str, size_type pos = 0,
             size_type n = npos, const Allocator& a = Allocator()); 

specifies an Allocator argument default value that is counter-intuitive. The natural choice for a the allocator to copy from is str.get_allocator(). Though this cannot be expressed in default-argument notation, overloading suffices.

and proposes these possible fixes:

B. In 21.3 [lib.basic.string], and also in 21.3.1 [lib.string.cons], replace the declaration of the copy constructor as follows:

basic_string(const basic_string& str, size_type pos = 0,
             size_type n = npos);

C. In 21.3 [lib.basic.string], replace the declaration of the copy constructor as follows:

basic_string(const basic_string& str);
basic_string(const basic_string& str, size_type pos, size_type n = npos,
             const Allocator& a = Allocator());

In 21.3.1 [lib.string.cons], replace the copy constructor declaration as above. Add to paragraph 5, Effects:

In the first form, the Allocator value used is copied from str.get_allocator().

The first fix matches the original SO answer the OP points to and the second matches what we have today.

This LWG issue is from 1998 which is probably why none of the public drafts available today have any evidence of this. The earliest public draft available N1804 is from 2005. What changes took place between 1998 and 2005 are not clear.

Melanesian answered 6/10, 2015 at 18:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.