Topic: emplace() overloads


Author: Greg Herlihy <greghe@mac.com>
Date: Wed, 28 Nov 2007 12:59:28 CST
Raw View
On Nov 27, 8:45 am, Sylvain Pion <Sylvain.P...@sophia.inria.fr> wrote:
> Greg Herlihy a    crit :
>
> >> What if I wish to pass a const_iterator as first argument and mean
> >> to use the first overload?
>
> > In that case you would assign the return value of the emplace()
> > function call to a pair<iterator, bool> - since only the first version
> > of emplace() returns a std::pair..
>
> C++ does not support overload selection by the return type, so I still
> can't select the one I want.  At best I get a compile error.

Assigning the result to a std::pair will ensure that the first version
of emplace() is called - because template type deduction -does- deduce
the return type of the function template - from the function call. So
constraining that return type to a std::pair<> - means that type
deduction will succeed only for the first emplace() function template
and not the second. In other words, the second version of emplace()
will not even be considered as a candidate to handle the function
call.

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                      ]





Author: Mathias Gaunard <loufoque@gmail.com>
Date: Thu, 29 Nov 2007 11:07:42 CST
Raw View
On 26 nov, 18:41, int...@gmail.com wrote:

> Wouldn't you be able explicitly specify Args? I.e.:
>
> cont.emplace<const_iterator, value_type>(iter, value)

Why so many tricks to repair an obviously defective interface?

---
[ 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                      ]





Author: Sylvain Pion <Sylvain.Pion@sophia.inria.fr>
Date: Tue, 20 Nov 2007 12:16:07 CST
Raw View
In the current working draft N2461, I read that associative
containers provide:

template <class... Args> pair<iterator, bool> emplace(Args&&... args);
template <class... Args> iterator emplace(const_iterator position,
Args&&... args);

What if I wish to pass a const_iterator as first argument and mean
to use the first overload?

Is this an oversight, or is this a deliberate choice?
What about using a different name for one of the 2 overloads, in order
to prevent the clash?

--
Sylvain Pion
INRIA Sophia-Antipolis
Geometrica Project-Team
CGAL, http://cgal.org/

---
[ 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                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 20 Nov 2007 21:10:06 GMT
Raw View
Sylvain Pion ha scritto:
> In the current working draft N2461, I read that associative
> containers provide:
>
> template <class... Args> pair<iterator, bool> emplace(Args&&... args);
> template <class... Args> iterator emplace(const_iterator position,
> Args&&... args);
>
> What if I wish to pass a const_iterator as first argument and mean
> to use the first overload?
>

This situation might occur only under very specific circumstances. Let's
see when:

1) if the container is a map/multimap: the value_type is

  std::pair<const key_type, mapped_type>

so emplace() can only have up to two arguments. Because we know the
constructors of std::pair, if the first argument is a const_iterator,
then there must be a second argument and the const_iterator is used to
initialize an object of value key_type. Therefore key_type shall have
one constructor that can take exactly one parameter of type
const_iterator. The key type shall be complete at the point of
instantiation of the container, so such constructor can not mention the
const_iterator explicitly, but must be a template, for example like this:

   template <class T>
   key(T x);

(there might be other arguments with default values, but they won't make
much difference.) Now... what use can you make of a single iterator of a
type that you don't know? The only thing that comes to my mind is to
store it in some boost::any or other polymorphic container.

2) if the container is a set/multiset, then we have slightly more
freedom, because all parameters are used to initialize the value_type
which is the same as the key_type. For the same reasoning as above, the
constructor of the key_type must be a template, but now it can have two
parameters, which may constitute a range. This makes the situation more
likely to be useful, but still I can't imagine a practical use case
realizing this scenario.

> Is this an oversight, or is this a deliberate choice?
> What about using a different name for one of the 2 overloads, in order
> to prevent the clash?
>

I believe this is a deliberate choice, but even if it weren't I suggest
you provide a strong and reasonable use-case where a disambiguation is
necessary before proposing a change.

HTH,

Ganesh

---
[ 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                      ]





Author: Daphne Pfister <lanatha@gmail.com>
Date: Tue, 20 Nov 2007 16:48:12 CST
Raw View
On Nov 20, 1:16 pm, Sylvain Pion <Sylvain.P...@sophia.inria.fr> wrote:
> In the current working draft N2461, I read that associative
> containers provide:
>
> template <class... Args> pair<iterator, bool> emplace(Args&&... args);
> template <class... Args> iterator emplace(const_iterator position,
> Args&&... args);
>
> What if I wish to pass a const_iterator as first argument and mean
> to use the first overload?
>
> Is this an oversight, or is this a deliberate choice?
> What about using a different name for one of the 2 overloads, in order
> to prevent the clash?
It seems to me that it would be unlikely that an iterator compatible
with the associative container would be able to construct a value into
the container. In the case* that foo is constructible from a constant
iterator using setname.emplace(setname.begin(),const_iter) should
work.

* I could see using a set for example as a type of tree where
value_type could be constructed with a reference to a parent node
which could be converted from a iterator..

class scope {
public:
  // Using concepts in the next line would be better...
  // just using this pseudo-code for an example.
  template <typename parent_iter> scope(parent_iter const& x) :
parent_(*x) {}
  scope() : parent_(*this) {}
  ...
  scole const& parent_;
};

.
typedef std::unordered_set<scope> scope_set
scope_set scopes;
scope_set::const_iterator root_scope = scopes.emplace().first;
scope_set::const_iterator active_scope = root_scope;
.
if (token == "{") {
  // active_scope = scopes.emplace(active_scope);
  active_scope = scopes.emplace(scope_set.end(),active_scope);
  ...
}
.

---
[ 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                      ]





Author: Sylvain Pion <Sylvain.Pion@sophia.inria.fr>
Date: Wed, 21 Nov 2007 11:57:34 CST
Raw View
Alberto Ganesh Barbati a   crit :
> Sylvain Pion ha scritto:
>> In the current working draft N2461, I read that associative
>> containers provide:
>>
>> template <class... Args> pair<iterator, bool> emplace(Args&&... args);
>> template <class... Args> iterator emplace(const_iterator position,
>> Args&&... args);
>>
>> What if I wish to pass a const_iterator as first argument and mean
>> to use the first overload?
>>
>
> This situation might occur only under very specific circumstances. Let's
> see when:
>
> 1) if the container is a map/multimap: the value_type is
>
>   std::pair<const key_type, mapped_type>
>
> so emplace() can only have up to two arguments. Because we know the
> constructors of std::pair, if the first argument is a const_iterator,
> then there must be a second argument and the const_iterator is used to
> initialize an object of value key_type. Therefore key_type shall have
> one constructor that can take exactly one parameter of type
> const_iterator. The key type shall be complete at the point of
> instantiation of the container,

I know this rule, although I never got the rationale for this
restriction.  At least g++'s std::list and std::set do not appear
to need this, and it seems to me that it is a feature that is worth
supporting.  Does anybody know a reason for this?

It is true that this argument cuts down most reasons to use
what I'm asking.

 >                               so such constructor can not mention the
> const_iterator explicitly, but must be a template, for example like this:
>
>    template <class T>
>    key(T x);
>
> (there might be other arguments with default values, but they won't make
> much difference.) Now... what use can you make of a single iterator of a
> type that you don't know? The only thing that comes to my mind is to
> store it in some boost::any or other polymorphic container.
>
> 2) if the container is a set/multiset, then we have slightly more
> freedom, because all parameters are used to initialize the value_type
> which is the same as the key_type. For the same reasoning as above, the
> constructor of the key_type must be a template, but now it can have two
> parameters, which may constitute a range. This makes the situation more
> likely to be useful, but still I can't imagine a practical use case
> realizing this scenario.
>
>> Is this an oversight, or is this a deliberate choice?
>> What about using a different name for one of the 2 overloads, in order
>> to prevent the clash?
>
> I believe this is a deliberate choice, but even if it weren't I suggest
> you provide a strong and reasonable use-case where a disambiguation is
> necessary before proposing a change.

Indeed, I should have expanded more on my use-case from the start.

I do not need the feature exactly, although my current use-case
is close enough to it, that I guess there is a risk that somebody
else might hit it at some point.

Basically, I store the nodes of a graph in a container.
Each node stores iterators pointing to other nodes (its neighbors
in the graph), and the node type's constructor takes such
iterators as arguments, including the first argument.
Now, the "container" that I am using is not a standard one,
for various reasons, but I would love to be able to use those as
well.

So, the differences between my use-case and what I'm asking, are:
- I need the "value_type needs to be complete before instantiating
   the container" restriction removed.
- I use iterator instead of const_iterator.
- I am also more interested in std::list (which does not have the
   overloaded emplace() issue), but I might be interested in std::set
   as well in some future.

My impression is that what prevents me from doing that is only
a set of gratuitous problems that could be dealt with.

Now, if people feel comfortable enough taking this risk, that's
fine for me.  I'm not sure the cost of finding another name
for the function to separate the 2 overloads would be that great
either (?).

--
Sylvain Pion
INRIA Sophia-Antipolis
Geometrica Project-Team
CGAL, http://cgal.org/

---
[ 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                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Wed, 21 Nov 2007 21:07:21 GMT
Raw View
Daphne Pfister ha scritto:
> On Nov 20, 1:16 pm, Sylvain Pion <Sylvain.P...@sophia.inria.fr> wrote:
>> In the current working draft N2461, I read that associative
>> containers provide:
>>
>> template <class... Args> pair<iterator, bool> emplace(Args&&... args);
>> template <class... Args> iterator emplace(const_iterator position,
>> Args&&... args);
>>
>> What if I wish to pass a const_iterator as first argument and mean
>> to use the first overload?
>>
>> Is this an oversight, or is this a deliberate choice?
>> What about using a different name for one of the 2 overloads, in order
>> to prevent the clash?
> It seems to me that it would be unlikely that an iterator compatible
> with the associative container would be able to construct a value into
> the container. In the case* that foo is constructible from a constant
> iterator using setname.emplace(setname.begin(),const_iter) should
> work.
>
> * I could see using a set for example as a type of tree where
> value_type could be constructed with a reference to a parent node
> which could be converted from a iterator..
>
> class scope {
> public:
>   // Using concepts in the next line would be better...
>   // just using this pseudo-code for an example.
>   template <typename parent_iter> scope(parent_iter const& x) :
> parent_(*x) {}
>   scope() : parent_(*this) {}
>   ...
>   scole const& parent_;
> };
>
> .
> typedef std::unordered_set<scope> scope_set
> scope_set scopes;
> scope_set::const_iterator root_scope = scopes.emplace().first;
> scope_set::const_iterator active_scope = root_scope;
> .
> if (token == "{") {
>   // active_scope = scopes.emplace(active_scope);
>   active_scope = scopes.emplace(scope_set.end(),active_scope);
>   ...
> }

That's a nice example. Please notice that there is another simple way to
rewrite

  // active_scope = scopes.emplace(active_scope);

with "non-hinted" semantic in addition to:

  active_scope = scopes.emplace(scope_set.end(),active_scope);

and that is:

  active_scope = scopes.emplace(scope(active_scope));

if scope has a cheap move constructor and the compiler is reasonably
optimizing, I don't expect to see significant performance differences.

HTH,

Ganesh

---
[ 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                      ]





Author: Greg Herlihy <greghe@mac.com>
Date: Mon, 26 Nov 2007 11:39:04 CST
Raw View
On Nov 20, 10:16 am, Sylvain Pion <Sylvain.P...@sophia.inria.fr>
wrote:
> In the current working draft N2461, I read that associative
> containers provide:
>
> template <class... Args> pair<iterator, bool> emplace(Args&&... args);
> template <class... Args> iterator emplace(const_iterator position,
> Args&&... args);
>
> What if I wish to pass a const_iterator as first argument and mean
> to use the first overload?

In that case you would assign the return value of the emplace()
function call to a pair<iterator, bool> - since only the first version
of emplace() returns a std::pair..

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                      ]





Author: int19h@gmail.com
Date: Mon, 26 Nov 2007 11:41:20 CST
Raw View
On Nov 20, 9:16 pm, Sylvain Pion <Sylvain.P...@sophia.inria.fr> wrote:

> In the current working draft N2461, I read that associative
> containers provide:
>
> template <class... Args> pair<iterator, bool> emplace(Args&&... args);
> template <class... Args> iterator emplace(const_iterator position,
> Args&&... args);
>
> What if I wish to pass a const_iterator as first argument and mean
> to use the first overload?

Wouldn't you be able explicitly specify Args? I.e.:

cont.emplace<const_iterator, value_type>(iter, value)

---
[ 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                      ]





Author: Sylvain Pion <Sylvain.Pion@sophia.inria.fr>
Date: Tue, 27 Nov 2007 09:46:33 CST
Raw View
Greg Herlihy a    crit :
> On Nov 20, 10:16 am, Sylvain Pion <Sylvain.P...@sophia.inria.fr>
> wrote:
>> In the current working draft N2461, I read that associative
>> containers provide:
>>
>> template <class... Args> pair<iterator, bool> emplace(Args&&... args);
>> template <class... Args> iterator emplace(const_iterator position,
>> Args&&... args);
>>
>> What if I wish to pass a const_iterator as first argument and mean
>> to use the first overload?
>
> In that case you would assign the return value of the emplace()
> function call to a pair<iterator, bool> - since only the first version
> of emplace() returns a std::pair..

C++ does not support overload selection by the return type, so I still
can't select the one I want this way.  At best I get a compile error.

--
Sylvain Pion
INRIA Sophia-Antipolis
Geometrica Project-Team
CGAL, http://cgal.org/

---
[ 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                      ]





Author: Sylvain Pion <Sylvain.Pion@sophia.inria.fr>
Date: Tue, 27 Nov 2007 10:45:59 CST
Raw View
Greg Herlihy a    crit :
> On Nov 20, 10:16 am, Sylvain Pion <Sylvain.P...@sophia.inria.fr>
> wrote:
>> In the current working draft N2461, I read that associative
>> containers provide:
>>
>> template <class... Args> pair<iterator, bool> emplace(Args&&... args);
>> template <class... Args> iterator emplace(const_iterator position,
>> Args&&... args);
>>
>> What if I wish to pass a const_iterator as first argument and mean
>> to use the first overload?
>
> In that case you would assign the return value of the emplace()
> function call to a pair<iterator, bool> - since only the first version
> of emplace() returns a std::pair..

C++ does not support overload selection by the return type, so I still
can't select the one I want.  At best I get a compile error.

--
Sylvain Pion
INRIA Sophia-Antipolis
Geometrica Project-Team
CGAL, http://cgal.org/

---
[ 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                      ]





Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Tue, 27 Nov 2007 13:12:18 CST
Raw View
On 26 Nov., 18:41, int...@gmail.com wrote:
> On Nov 20, 9:16 pm, Sylvain Pion <Sylvain.P...@sophia.inria.fr> wrote:
> Wouldn't you be able explicitly specify Args? I.e.:
>
> cont.emplace<const_iterator, value_type>(iter, value)

I would say that it is implementation-defined, whether this
expression is well-formed or not. Due to the freedom given
in [lib.member.functions]/2+3 it is not guaranteed that
exactly this signature exists.

Greetings from Bremen,

Daniel Kr   gler

---
[ 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                      ]





Author: Sylvain.Pion@sophia.inria.fr (Sylvain Pion)
Date: Tue, 27 Nov 2007 20:12:07 GMT
Raw View
int19h@gmail.com a =E9crit :
> On Nov 20, 9:16 pm, Sylvain Pion <Sylvain.P...@sophia.inria.fr> wrote:
>=20
>> In the current working draft N2461, I read that associative
>> containers provide:
>>
>> template <class... Args> pair<iterator, bool> emplace(Args&&... args);
>> template <class... Args> iterator emplace(const_iterator position,
>> Args&&... args);
>>
>> What if I wish to pass a const_iterator as first argument and mean
>> to use the first overload?
>=20
> Wouldn't you be able explicitly specify Args? I.e.:
>=20
> cont.emplace<const_iterator, value_type>(iter, value)

This would work, indeed.  I find it inconvenient, though.
But maybe it is less inconvenient than introducing a different name...

--=20
Sylvain Pion
INRIA Sophia-Antipolis
Geometrica Project-Team
CGAL, http://cgal.org/

---
[ 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                      ]