Topic: Map find wrapper


Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Sun, 27 Jan 2013 06:02:50 -0800 (PST)
Raw View
------=_Part_279_16577175.1359295370059
Content-Type: text/plain; charset=ISO-8859-1

A lot of code using (unordered) map::find looks like:

typedef std::map<std::string, int> mapT;
mapT my_map;

mapT::iterator it = my_map.find("x");
if (it != my_map.end())
  std::cout << "A: " << it->second << "\n";

A more convenient variant using a wrapper looks like:

if (int* it = find_ptr(my_map, "x"))
  std::cout << "A: " << *it << "\n";

The wrapper would return a pointer to second if the key is found or NULL if
it isn't.

Advantages:
The map (name) is only mentioned once.
The check is simpler and can be combined with the definition.
The return type name is simpler (if auto isn't used).
Dereferencing the returned pointer is simpler as using second isn't
necessary.

The majority of map::find use cases could benefit from such a wrapper.
What do you think?

http://www.cplusplus.com/reference/map/map/find/
http://en.cppreference.com/w/cpp/container/map/find
http://msdn.microsoft.com/en-us/library/92cwhskb(v=vs.80).aspx

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



------=_Part_279_16577175.1359295370059
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div>A lot of code using (unordered) map::find looks like:</div><div><br></=
div><div>typedef std::map&lt;std::string, int&gt; mapT;</div><div>mapT my_m=
ap;</div><div><br></div><div>mapT::iterator it =3D my_map.find("x");</div><=
div>if (it !=3D my_map.end())&nbsp;</div><div>&nbsp; std::cout &lt;&lt; "A:=
 " &lt;&lt; it-&gt;second &lt;&lt; "\n";</div><div><br></div><div>A more co=
nvenient variant using a wrapper looks like:</div><div><br></div><div>if (i=
nt* it =3D find_ptr(my_map, "x"))&nbsp;</div><div>&nbsp; std::cout &lt;&lt;=
 "A: " &lt;&lt; *it &lt;&lt; "\n";</div><div><br></div><div>The wrapper wou=
ld return a pointer to second if the key is found or NULL if it isn't.</div=
><div><br></div><div>Advantages:</div><div>The map (name) is only mentioned=
 once.</div><div>The check is simpler and can be combined with the definiti=
on.</div><div>The return type name is simpler (if auto isn't used).</div><d=
iv>Dereferencing the returned pointer is simpler as using second isn't nece=
ssary.</div><div><br></div><div>The majority of map::find use cases could b=
enefit from such a wrapper.</div><div>What do you think?</div><div><br></di=
v><div>http://www.cplusplus.com/reference/map/map/find/</div><div>http://en=
..cppreference.com/w/cpp/container/map/find</div><div>http://msdn.microsoft.=
com/en-us/library/92cwhskb(v=3Dvs.80).aspx</div><div><br></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
To unsubscribe from this group, send email to std-proposals+unsubscribe@iso=
cpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

------=_Part_279_16577175.1359295370059--

.


Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Sun, 27 Jan 2013 15:08:36 +0100
Raw View
2013/1/27 Olaf van der Spek <olafvdspek@gmail.com>:
> A lot of code using (unordered) map::find looks like:
>
> typedef std::map<std::string, int> mapT;
> mapT my_map;
>
> mapT::iterator it = my_map.find("x");
> if (it != my_map.end())
>   std::cout << "A: " << it->second << "\n";
>
> A more convenient variant using a wrapper looks like:
>
> if (int* it = find_ptr(my_map, "x"))
>   std::cout << "A: " << *it << "\n";
>
> The wrapper would return a pointer to second if the key is found or NULL if
> it isn't.
>
> Advantages:
> The map (name) is only mentioned once.
> The check is simpler and can be combined with the definition.
> The return type name is simpler (if auto isn't used).
> Dereferencing the returned pointer is simpler as using second isn't
> necessary.
>
> The majority of map::find use cases could benefit from such a wrapper.
> What do you think?

I tend to agree. I'm not sure about the best choice for the name (but
this problem became already obvious during the optional discussion),
but except from that I think that this is a useful addition for
non-multi maps.

- Daniel

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 27 Jan 2013 16:16:35 +0200
Raw View
On 27 January 2013 16:08, Daniel Kr=FCgler <daniel.kruegler@gmail.com> wrot=
e:
>> if (int* it =3D find_ptr(my_map, "x"))
>>   std::cout << "A: " << *it << "\n";
>> The wrapper would return a pointer to second if the key is found or NULL=
 if
>> it isn't.
>> Advantages:
>> The map (name) is only mentioned once.
>> The check is simpler and can be combined with the definition.
>> The return type name is simpler (if auto isn't used).
>> Dereferencing the returned pointer is simpler as using second isn't
>> necessary.
>> The majority of map::find use cases could benefit from such a wrapper.
>> What do you think?
> I tend to agree. I'm not sure about the best choice for the name (but
> this problem became already obvious during the optional discussion),
> but except from that I think that this is a useful addition for
> non-multi maps.

Perhaps it should return an iterator wrapper so that the key is available
for use, and have a simple boolean conversion for the conditional?

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@iso=
cpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/?hl=3Den.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 27 Jan 2013 17:16:25 +0200
Raw View
On 27 January 2013 16:16, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
> Perhaps it should return an iterator wrapper so that the key is available
> for use, and have a simple boolean conversion for the conditional?

In other words

#include <vector>
#include <map>
#include <algorithm>
#include <iostream>

template <class C, class I>
struct find_iterator
{
  C& container;
  I iterator;
  find_iterator(C& c, I i) : container(c), iterator(i) {}
  explicit operator bool() {return iterator != end(container);}
  I operator->()  {return iterator;}
  auto operator*() -> decltype(*iterator) {return *iterator;}
};

template <class C, class I>
find_iterator<C, I> make_find_iterator(C& c, I i)
{
  return find_iterator<C, I>(c, i);
}

int main()
{
  std::vector<int> x{1, 4, 9};
  auto foo = make_find_iterator(x, std::find(x.begin(), x.end(), 4));
  if (foo)
    std::cout << "found " << *foo << " in vector" << std::endl;
  auto foo2 = make_find_iterator(x, std::find(x.begin(), x.end(), 3));
  if (!foo2)
    std::cout << "not found 3" << " in vector" << std::endl;
  std::map<int, int> y{{1,2},{3, 4}, {5, 6}};
  auto bar = make_find_iterator(y, y.find(3));
  if (bar)
    std::cout << "found " << bar->first << " in map with value " <<
bar->second << std::endl;
  auto bar2 = make_find_iterator(y, y.find(2));
  if (bar)
    std::cout << "not found 2 in map " << std::endl;

}

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 27 Jan 2013 17:35:39 +0200
Raw View
On 27 January 2013 17:16, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
> On 27 January 2013 16:16, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
>> Perhaps it should return an iterator wrapper so that the key is available
>> for use, and have a simple boolean conversion for the conditional?
> In other words

With a default template argument, I can get it down to

find_iterator<decltype(y)> bar3{y, y.find(4)};

on the using side, without sacrificing generality. I can't figure out
how to get rid of the multiple
mentioning of x.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Arthur Tchaikovsky <atch.cpp@gmail.com>
Date: Sun, 27 Jan 2013 15:43:20 +0000
Raw View
Hi Ville,
Just some "not too much C++11" check ;);

auto operator*() -> decltype(*iterator) {return *iterator;}

There is no need here for auto, you can simply state:

 decltype(*iterator) operator*()
 {
        return *iterator;
 }



On 1/27/13, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
> On 27 January 2013 16:16, Ville Voutilainen <ville.voutilainen@gmail.com>
> wrote:
>> Perhaps it should return an iterator wrapper so that the key is available
>> for use, and have a simple boolean conversion for the conditional?
>
> In other words
>
> #include <vector>
> #include <map>
> #include <algorithm>
> #include <iostream>
>
> template <class C, class I>
> struct find_iterator
> {
>   C& container;
>   I iterator;
>   find_iterator(C& c, I i) : container(c), iterator(i) {}
>   explicit operator bool() {return iterator != end(container);}
>   I operator->()  {return iterator;}
>   auto operator*() -> decltype(*iterator) {return *iterator;}
> };
>
> template <class C, class I>
> find_iterator<C, I> make_find_iterator(C& c, I i)
> {
>   return find_iterator<C, I>(c, i);
> }
>
> int main()
> {
>   std::vector<int> x{1, 4, 9};
>   auto foo = make_find_iterator(x, std::find(x.begin(), x.end(), 4));
>   if (foo)
>     std::cout << "found " << *foo << " in vector" << std::endl;
>   auto foo2 = make_find_iterator(x, std::find(x.begin(), x.end(), 3));
>   if (!foo2)
>     std::cout << "not found 3" << " in vector" << std::endl;
>   std::map<int, int> y{{1,2},{3, 4}, {5, 6}};
>   auto bar = make_find_iterator(y, y.find(3));
>   if (bar)
>     std::cout << "found " << bar->first << " in map with value " <<
> bar->second << std::endl;
>   auto bar2 = make_find_iterator(y, y.find(2));
>   if (bar)
>     std::cout << "not found 2 in map " << std::endl;
>
> }
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To post to this group, send email to std-proposals@isocpp.org.
> To unsubscribe from this group, send email to
> std-proposals+unsubscribe@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
>
>
>

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 27 Jan 2013 17:57:43 +0200
Raw View
On 27 January 2013 17:43, Arthur Tchaikovsky <atch.cpp@gmail.com> wrote:
> auto operator*() -> decltype(*iterator) {return *iterator;}
> There is no need here for auto, you can simply state:
>  decltype(*iterator) operator*()

Sure. The implementation was a bit quick&dirty. Anyway, the real
questions we want to
ask are these:
1) do we want to add a dozen algorithm wrappers that return some
handier return types
than a bare iterator?
2) do we want to add a couple of such wrappers to maps and sets?
3) do we want a generic utility that can wrap all current algorithms
(the find_iterator),
but is not as convenient otherwise?
4) regarding (1) and (2), what happens when the range crowd arrives
with their 40 new
algorithm overloads? What happens when the parallelism crowd arrives
with their 40
new algorithms?

What Olaf proposes is certainly handy. I have doubts about how to
solve the problem
at hand in a clean manner.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Matias Capeletto <matias.capeletto@gmail.com>
Date: Sun, 27 Jan 2013 17:33:29 +0100
Raw View
On Sun, Jan 27, 2013 at 3:02 PM, Olaf van der Spek <olafvdspek@gmail.com> wrote:
> A more convenient variant using a wrapper looks like:
>
> if (int* it = find_ptr(my_map, "x"))
>   std::cout << "A: " << *it << "\n";
>
> The wrapper would return a pointer to second if the key is found or NULL if
> it isn't.

If optional gets into the standard, shouldn't we be thinking on something like:

if( optional<mapped_type> opt_val = find_opt(my_map,"x")) )
  cout << "A: " << *opt_val << "\n";

Conceptually, it seems that we want to express exactly what optional
is built for. For the return type, an optional iterator could also be
returned instead.

Best regards
Matias

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Matias Capeletto <matias.capeletto@gmail.com>
Date: Sun, 27 Jan 2013 17:52:53 +0100
Raw View
On Sun, Jan 27, 2013 at 5:33 PM, Matias Capeletto
<matias.capeletto@gmail.com> wrote:
> Conceptually, it seems that we want to express exactly what optional
> is built for. For the return type, an optional iterator could also be
> returned instead.

Actually, the iterator version looks a lot better:

if( auto opt_iter = find_opt(my_map,"x")) )
  cout << "A: " << opt_iter->second << "\n";

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 27 Jan 2013 20:02:39 +0200
Raw View
On 27 January 2013 18:33, Matias Capeletto <matias.capeletto@gmail.com> wrote:
> If optional gets into the standard, shouldn't we be thinking on something like:
> if( optional<mapped_type> opt_val = find_opt(my_map,"x")) )
>   cout << "A: " << *opt_val << "\n";
> Conceptually, it seems that we want to express exactly what optional
> is built for. For the return type, an optional iterator could also be
> returned instead.

Returning an optional<mapped> or an optional<iterator> will close the door
on composability - returning an iterator that may point to end()
allows composing
such algorithms with others. That was not the reason why I wrote my
find_iterator,
I wrote it to keep access to the key as well as the value, but having
the original
iterator around is a nice bonus.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: DeadMG <wolfeinstein@gmail.com>
Date: Sun, 27 Jan 2013 10:33:22 -0800 (PST)
Raw View
------=_Part_463_4565682.1359311602163
Content-Type: text/plain; charset=ISO-8859-1

Conceptually, I think the solution is that optional<T> should be a range of
0 or 1 elements itself.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



------=_Part_463_4565682.1359311602163
Content-Type: text/html; charset=ISO-8859-1

Conceptually, I think the solution is that optional&lt;T&gt; should be a range of 0 or 1 elements itself.

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
&nbsp;<br />
&nbsp;<br />

------=_Part_463_4565682.1359311602163--

.


Author: Matias Capeletto <matias.capeletto@gmail.com>
Date: Sun, 27 Jan 2013 19:33:47 +0100
Raw View
On Sun, Jan 27, 2013 at 7:02 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 27 January 2013 18:33, Matias Capeletto <matias.capeletto@gmail.com> wrote:
>> If optional gets into the standard, shouldn't we be thinking on something like:
>> if( optional<mapped_type> opt_val = find_opt(my_map,"x")) )
>>   cout << "A: " << *opt_val << "\n";
>> Conceptually, it seems that we want to express exactly what optional
>> is built for. For the return type, an optional iterator could also be
>> returned instead.
>
> Returning an optional<mapped> or an optional<iterator> will close the door
> on composability - returning an iterator that may point to end()
> allows composing
> such algorithms with others. That was not the reason why I wrote my
> find_iterator,
> I wrote it to keep access to the key as well as the value, but having
> the original
> iterator around is a nice bonus.

Yes, you are right. I was thinking only in the original case that
originated the thread.
And actually, to solve it anyone could just use their own function:

template<class Container,class Iterator>
optional<Iterator> make_opt(Container& c,Iterator iter) {
  return iter != end(c) ? iter : nullopt ;
}
....
if( auto opt_iter = make_opt(m,find(m,"x")) ) {
  cout << opt_iter->second ;
}

About composability, how do you see make_find_iterator being used?

Best regards
Matias

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 27 Jan 2013 22:09:50 +0200
Raw View
On 27 January 2013 20:33, Matias Capeletto <matias.capeletto@gmail.com> wrote:
> And actually, to solve it anyone could just use their own function:
> template<class Container,class Iterator>
> optional<Iterator> make_opt(Container& c,Iterator iter) {
>   return iter != end(c) ? iter : nullopt ;
> }
> if( auto opt_iter = make_opt(m,find(m,"x")) ) {
>   cout << opt_iter->second ;
> }
> About composability, how do you see make_find_iterator being used?

Oh, that's just a reflex - to write a make-function for a class template so that
the template arguments can be deduced. With decltype, we don't need it:

#include <vector>
#include <map>
#include <algorithm>
#include <iostream>

template <class C, class I=typename C::iterator>
struct find_iterator
{
  C& container;
  I iterator;
  find_iterator(C& c, I i) : container(c), iterator(i) {}
  explicit operator bool() {return iterator != end(container);}
  I operator->()  {return iterator;}
  auto operator*() -> decltype(*iterator) {return *iterator;}
};

int main()
{
  std::vector<int> x{1, 4, 9};
  auto foo = find_iterator<decltype(x)>{x, std::find(x.begin(), x.end(), 4)};
  if (foo)
    std::cout << "found " << *foo << " in vector" << std::endl;
  find_iterator<decltype(x)> foo2{x, std::find(x.begin(), x.end(), 3)};
  if (!foo2)
    std::cout << "not found 3" << " in vector" << std::endl;
  std::map<int, int> y{{1,2},{3, 4}, {5, 6}};
  auto bar = find_iterator<decltype(y)>{y, y.find(3)};
  if (bar)
    std::cout << "found " << bar->first << " in map with value " <<
bar->second << std::endl;
  find_iterator<decltype(y)> bar2{y, y.find(2)};
  if (bar)
    std::cout << "not found 2 in map " << std::endl;
}

There's some mixing of auto and typed variables there, just to get the
taste of it. As I said
before, having a default template argument and decltype does reduce it to

  find_iterator<decltype(y)> bar2{y, y.find(2)};

which looks pretty decent to me, and it still allows using
find_iterator with non-default iterator
types (which might actually benefit from a make_find_iterator()), and
it keeps the original
iterator type, allowing composition and access to the original element
pointed to by
the original iterator. It requires mentioning y above twice, but it's
getting tolerable.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Matias Capeletto <matias.capeletto@gmail.com>
Date: Sun, 27 Jan 2013 21:18:51 +0100
Raw View
On Sun, Jan 27, 2013 at 9:09 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
>> About composability, how do you see make_find_iterator being used?
>
> Oh, that's just a reflex - to write a make-function for a class template so that
> the template arguments can be deduced.

I wasn't referring to this, actually I wrote make_opt in my last mail
because of the same reason. And even with decltype, I still see the
value of the make-function.

> ... allowing composition and access to the original element
> pointed to by
> the original iterator.

This is what I was asking, how do you plan to compose your
find_iterators? It doesn't seems that they will work well in
functional composition, except that you start to have algorithms that
expect this new concept. And if you are using it in the same function
context, it seems that you still have the container there at hand to
work with so you can actually can get the end iterator with out it
being stored in find_iterator. I was curious about how the different
composition scenarios you see for your type.

Best regards
Matias

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Daniel James <dnljms@gmail.com>
Date: Sun, 27 Jan 2013 20:23:17 +0000
Raw View
On 27 January 2013 15:16, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
> template <class C, class I>
> struct find_iterator
> {
>   C& container;
>   I iterator;
>   find_iterator(C& c, I i) : container(c), iterator(i) {}
>   explicit operator bool() {return iterator != end(container);}
>   I operator->()  {return iterator;}
>   auto operator*() -> decltype(*iterator) {return *iterator;}
> };

Does this do anything that you can't do with a range?

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Jeffrey Yasskin <jyasskin@googlers.com>
Date: Sun, 27 Jan 2013 12:27:39 -0800
Raw View
On Sun, Jan 27, 2013 at 6:16 AM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 27 January 2013 16:08, Daniel Kr=FCgler <daniel.kruegler@gmail.com> wr=
ote:
>>> if (int* it =3D find_ptr(my_map, "x"))
>>>   std::cout << "A: " << *it << "\n";
>>> The wrapper would return a pointer to second if the key is found or NUL=
L if
>>> it isn't.
>>> Advantages:
>>> The map (name) is only mentioned once.
>>> The check is simpler and can be combined with the definition.
>>> The return type name is simpler (if auto isn't used).
>>> Dereferencing the returned pointer is simpler as using second isn't
>>> necessary.
>>> The majority of map::find use cases could benefit from such a wrapper.
>>> What do you think?
>> I tend to agree. I'm not sure about the best choice for the name (but
>> this problem became already obvious during the optional discussion),
>> but except from that I think that this is a useful addition for
>> non-multi maps.
>
> Perhaps it should return an iterator wrapper so that the key is available
> for use, and have a simple boolean conversion for the conditional?

FWIW, I've used the find-or-null function a bunch, and I don't think
I've ever cared if I could get the key or iterator out of it. This
tool is helpful for end users and doesn't need to be overdesigned for
the benefit of library authors.

I've also used a function that works on maps of T* and returns a NULL
T* instead of a NULL T**, but that can be generalized to
"find-or-default-construct", and I've used a find-or-die function,
which is now equivalent to map::at(). I don't think I've run into any
particular need to use this with algorithms other than find().

Having the new range algorithms return an optional<iterator> instead
of failing with end(range) may make sense, but should probably be
discussed in SG9.

Jeffrey

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@iso=
cpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/?hl=3Den.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 27 Jan 2013 22:40:12 +0200
Raw View
On 27 January 2013 22:18, Matias Capeletto <matias.capeletto@gmail.com> wrote:
> I wasn't referring to this, actually I wrote make_opt in my last mail
> because of the same reason. And even with decltype, I still see the
> value of the make-function.

Sure, it's useful for some cases.

> This is what I was asking, how do you plan to compose your
> find_iterators? It doesn't seems that they will work well in

I can't do it directly as the example is written, but I can use find_iterator's
iterator member. I could also add a conversion function, but that's rarely
useful with type-deducing algorithm templates.

> functional composition, except that you start to have algorithms that
> expect this new concept. And if you are using it in the same function
> context, it seems that you still have the container there at hand to
> work with so you can actually can get the end iterator with out it
> being stored in find_iterator. I was curious about how the different
> composition scenarios you see for your type.

I didn't think of scenarios where I'd pass find_iterator directly to other
algorithms, I always expected to use its underlying iterator, which
is available as a public data member.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 27 Jan 2013 22:44:27 +0200
Raw View
On 27 January 2013 22:23, Daniel James <dnljms@gmail.com> wrote:
> On 27 January 2013 15:16, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
>> template <class C, class I>
>> struct find_iterator
>> {
>>   C& container;
>>   I iterator;
> Does this do anything that you can't do with a range?

I don't know. I'm not familiar with boost::range, so perhaps it
already has something
like this. I can write such a simple wrapper easily regardless of
whether I have boost
at my disposal. The question is, do we want a new algorithm that
returns an optional
object, or do we want an adapter that can use existing algorithms. If
we add a range
algorithm, it'll be interesting to see what it'll return, a position,
an optional, or what.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Sun, 27 Jan 2013 22:42:59 +0100
Raw View
On Sun, Jan 27, 2013 at 9:27 PM, Jeffrey Yasskin <jyasskin@googlers.com> wrote:
> FWIW, I've used the find-or-null function a bunch, and I don't think
> I've ever cared if I could get the key or iterator out of it. This
> tool is helpful for end users and doesn't need to be overdesigned for
> the benefit of library authors.
>
> I've also used a function that works on maps of T* and returns a NULL
> T* instead of a NULL T**, but that can be generalized to
> "find-or-default-construct", and I've used a find-or-die function,
> which is now equivalent to map::at(). I don't think I've run into any
> particular need to use this with algorithms other than find().

Damn, you just stole my find_ptr2 and find_ref functions. :p




--
Olaf

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 28 Jan 2013 14:18:15 +0100
Raw View
On Sun, Jan 27, 2013 at 3:08 PM, Daniel Kr=FCgler
<daniel.kruegler@gmail.com> wrote:
> I tend to agree. I'm not sure about the best choice for the name (but
> this problem became already obvious during the optional discussion),
> but except from that I think that this is a useful addition for
> non-multi maps.

Conceptually it'd work for sets and all other ranges too.


On Sun, Jan 27, 2013 at 4:16 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
>   auto bar =3D make_find_iterator(y, y.find(3));
>   if (bar)
>     std::cout << "found " << bar->first << " in map with value " <<
> bar->second << std::endl;

If access to the key is desired (it's not in most cases) you could
just as well return a pointer to value_type.


On Sun, Jan 27, 2013 at 4:35 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> With a default template argument, I can get it down to
>
> find_iterator<decltype(y)> bar3{y, y.find(4)};

Somehow I prefer auto bar3 =3D find_ptr(y, 4);


On Sun, Jan 27, 2013 at 4:57 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> Sure. The implementation was a bit quick&dirty. Anyway, the real
> questions we want to
> ask are these:
> 1) do we want to add a dozen algorithm wrappers that return some
> handier return types
> than a bare iterator?

What other frequently used algorhitms would benefit from this?

> 2) do we want to add a couple of such wrappers to maps and sets?

Yes, probably as non-member functions.

> 3) do we want a generic utility that can wrap all current algorithms
> (the find_iterator),
> but is not as convenient otherwise?

Probably not


7On Sun, Jan 27, 2013 at 5:33 PM, Matias Capeletto
<matias.capeletto@gmail.com> wrote:
> If optional gets into the standard, shouldn't we be thinking on something=
 like:
>
> if( optional<mapped_type> opt_val =3D find_opt(my_map,"x")) )
>   cout << "A: " << *opt_val << "\n";
>
> Conceptually, it seems that we want to express exactly what optional
> is built for. For the return type, an optional iterator could also be
> returned instead.

No, as it should be by reference, not by value.

--=20
Olaf

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@iso=
cpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/?hl=3Den.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Jan 2013 15:25:02 +0200
Raw View
On 28 January 2013 15:18, Olaf van der Spek <olafvdspek@gmail.com> wrote:
>>   auto bar = make_find_iterator(y, y.find(3));
>>   if (bar)
>>     std::cout << "found " << bar->first << " in map with value " <<
>> bar->second << std::endl;
> If access to the key is desired (it's not in most cases) you could
> just as well return a pointer to value_type.

Then I won't have the iterator.

>> With a default template argument, I can get it down to
>> find_iterator<decltype(y)> bar3{y, y.find(4)};
> Somehow I prefer auto bar3 = find_ptr(y, 4);

I don't disagree with that, it's much nicer and simpler for the user.

>> 1) do we want to add a dozen algorithm wrappers that return some
>> handier return types
>> than a bare iterator?
> What other frequently used algorhitms would benefit from this?

The point is that you may want to have it for both the find algorithm
and for member find.

>> 2) do we want to add a couple of such wrappers to maps and sets?
> Yes, probably as non-member functions.

Ok. The potential explosion of different algorithms concerns me. Seeing
the actual impact of this proposal + ranges + parallel algorithms will
be interesting.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 28 Jan 2013 14:36:47 +0100
Raw View
 On Mon, Jan 28, 2013 at 2:25 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 28 January 2013 15:18, Olaf van der Spek <olafvdspek@gmail.com> wrote:
>>>   auto bar = make_find_iterator(y, y.find(3));
>>>   if (bar)
>>>     std::cout << "found " << bar->first << " in map with value " <<
>>> bar->second << std::endl;
>> If access to the key is desired (it's not in most cases) you could
>> just as well return a pointer to value_type.
>
> Then I won't have the iterator.

Not a problem in the majority of cases.

>>> 1) do we want to add a dozen algorithm wrappers that return some
>>> handier return types
>>> than a bare iterator?
>> What other frequently used algorhitms would benefit from this?
>
> The point is that you may want to have it for both the find algorithm
> and for member find.

I assume there's still no way to call member find if it's available
and non-member find if it's not?

Anyway, I use member find all the time but I rarely use non-member find.


--
Olaf

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Jan 2013 15:45:04 +0200
Raw View
On 28 January 2013 15:36, Olaf van der Spek <olafvdspek@gmail.com> wrote:
>>> If access to the key is desired (it's not in most cases) you could
>>> just as well return a pointer to value_type.
>> Then I won't have the iterator.
> Not a problem in the majority of cases.

That's probably right. I haven't used the wrapper I wrote practically,
and I'm too
indoctrinated to actively wish for having something simpler than
iterator!=end().
Range-for gives me some of that convenience, so perhaps it's worthwhile.

>> The point is that you may want to have it for both the find algorithm
>> and for member find.
> I assume there's still no way to call member find if it's available
> and non-member find if it's not?

I don't think this proposal or the wrapper I wrote try to solve that problem.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 28 Jan 2013 14:46:27 +0100
Raw View
On Mon, Jan 28, 2013 at 2:45 PM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
>>> The point is that you may want to have it for both the find algorithm
>>> and for member find.
>> I assume there's still no way to call member find if it's available
>> and non-member find if it's not?
>
> I don't think this proposal or the wrapper I wrote try to solve that problem.

It doesn't, but it would allow this wrapper to be used with non-member find.

--
Olaf

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 28 Jan 2013 15:54:04 +0200
Raw View
On 28 January 2013 15:46, Olaf van der Spek <olafvdspek@gmail.com> wrote:
>>> I assume there's still no way to call member find if it's available
>>> and non-member find if it's not?
>> I don't think this proposal or the wrapper I wrote try to solve that problem.
> It doesn't, but it would allow this wrapper to be used with non-member find.

Ah, I see. That would certainly make this proposal more generic, I
like the idea.
Some SFINAE magic might be required, but then again, that's an implementation
detail that doesn't need to be spelled out in the specification, if
we're at least
confident it's implementable reasonably.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To post to this group, send email to std-proposals@isocpp.org.
To unsubscribe from this group, send email to std-proposals+unsubscribe@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.



.