Re: push_back<Args> and explicit constructors [Defect in the working draft]
On Nov 7, 12:56 pm, Magnus F <ma...@lysator.liu.se> wrote:
The problem I see is that in the 1998 standard push_back is declared
as
void vector<T, ...>::push_back(const T&)
while it, in n2461, is declared as
template <class... Args> void push_back(Args&&... args);
Now consider push_back(1), in the 1998 version the conversion sequence
is
int is _implicitly_ converted to a Foo that is inserted, but since
Foo(int) is explicit there is no valid conversion sequence so the code
is invalid.
in the n2461 version the conversion sequence is
int is handed to push_back, push_back(args) is equivalent to
a.emplace(a.end(), std::forward<Args>(args)...), that is
a.emplace(a.end(), 1), that in turn inserts an T(args), in this case
an Foo(1) and the big difference is that now Foo(1) is _explicitly_
called.
Yes, clearly Foo's constructor must be explicitly called in order to
construct the object (being added to the container) from whatever
arguments are provided. Otherwise, a C++09 program like the one below
- would not compile:
struct A
{
A() {}
A(int, int) {}
};
int main()
{
std::vector<A> v;
v.push_back(); // adds A() to v
v.push_back(1, 2); // adds A(1,2) to v
}
I want to make sure that the call to Foo(1) continues to be implicitly
called so that my example fails to compile in the future as well as we
would be degrading the value of explicit constructors otherwise.
Nothing about explicit constructors has changed. Only the containers'
declaration of puah_back() has changed - and been made more useful.
With the new interface, objects can now be added to a container by
constructing them "in place" - without any copying involved at all.
Moreover, the conversion from an int to a Foo when adding to the
container is hardly "implicit". There is no doubt which push_back()
method is being called here. Nor is the programmer in all likelihood
expecting an int to reside in a container of Foo's. So the only
plausible meaning of the push_back() call - is to construct a Foo from
the int argument provided.
In fact, it is important to view the situation the other way around.
Say a C++ programmer has an int - and a container of Foo's. Now, the
programmer wants to use the int to construct a Foo and add the newly-
constructed Foo to the end of the container. Assuming the programmer
wants to accomplish this task in the most efficient way possible - why
should an explicit constructor get in the way? If the explicit
constructor did get in the way - then the programmer would be faced
with a choice between safety and efficiency - a choice that should not
have to be made.
Lastly, this change breaks no existing C++ programs. True, code that
would not have compiled in the past will now compile in C++09, due to
this change. But the same could be said of any other extension to C++
- and therefore does not present much of an argument against making
the change.
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]