Opened 11 years ago

Closed 11 years ago

Last modified 11 years ago

#5991 closed Feature Requests (wontfix)

find_ptr (find wrapper)

Reported by: Olaf van der Spek <olafvdspek@…> Owned by: Joaquín M López Muñoz
Milestone: To Be Determined Component: multi_index
Version: Boost 1.47.0 Severity: Problem
Keywords: Cc:

Description

Could you add a find wrapper to multi_index that returns value_type* instead of an iterator (and NULL if not found)?

It'd allow code like:

if (auto i = c.find_ptr("key"))
{
}

Change History (11)

comment:1 by Joaquín M López Muñoz, 11 years ago

Resolution: wontfix
Status: newclosed

I don't think this is sufficiently useful as to be included in the general API of Boost.MultiIndex (for one, no container in STL or Boost does it.) In any case, you can roll your own find_ptr utility:

template<typename Container,typename Key>
const typename Container::value_type*
find_ptr(const Container&c,const Key& k)
{
  auto i=c.find(k);
  return i==c.end()?0:&*i;
}
...

if(auto p=find_ptr(c,5)){...}

in reply to:  1 ; comment:2 by Olaf van der Spek <olafvdspek@…>, 11 years ago

Replying to joaquin:

I don't think this is sufficiently useful as to be included in the general API of Boost.MultiIndex (for one, no container in STL or Boost does it.)

Someone has to be first, right?

In any case, you can roll your own find_ptr utility:

Already got one for std::map etc, but not yet for std::set. I thought multi_index required a different function, but it can use the same as std::set. So it probably shouldn't be a member function.

in reply to:  2 ; comment:3 by Joaquín M López Muñoz, 11 years ago

Replying to Olaf van der Spek <olafvdspek@…>:

Replying to joaquin:

I don't think this is sufficiently useful as to be included in the general API of Boost.MultiIndex (for one, no container in STL or Boost does it.)

Someone has to be first, right?

Yes of course, but in this case I don't think the use case presented is so prominent as to deserve a dedicated built-in feature.

In any case, you can roll your own find_ptr utility:

Already got one for std::map etc, but not yet for std::set. I thought multi_index required a different function, but it can use the same as std::set. So it probably shouldn't be a member function.

What's wrong with the example find_ptr function template given above? It should work with any container providing a find member function --I don't see the need to have separate functions for map, set, etc.

in reply to:  3 ; comment:4 by Olaf van der Spek <olafvdspek@…>, 11 years ago

Replying to joaquin:

Already got one for std::map etc, but not yet for std::set. I thought multi_index required a different function, but it can use the same as std::set. So it probably shouldn't be a member function.

What's wrong with the example find_ptr function template given above? It should work with any container providing a find member function --I don't see the need to have separate functions for map, set, etc.

The map variant returns a pointer to second. A variant for containers that store pointers performs an additional dereference. IMO the wrapper is useful every time you use a map like container.

comment:5 by Olaf van der Spek <olafvdspek@…>, 11 years ago

Joaquín?

in reply to:  4 ; comment:6 by Joaquín M López Muñoz, 11 years ago

Replying to Olaf van der Spek <olafvdspek@…>:

The map variant returns a pointer to second. A variant for containers that store pointers performs an additional dereference.

Why a pointer to second? This is not consistent with the semantics of std::map, which returns an iterator to the whole element (the key-value pair), not the value alone.

IMO the wrapper is useful every time you use a map like container.

In either case, find_ptr can be provided as an (overloaded) function, no need to have as a built-in member function. Thus my reluctance to address your request.

in reply to:  6 ; comment:7 by Olaf van der Spek <olafvdspek@…>, 11 years ago

Replying to joaquin:

Why a pointer to second?

Because the key is known already.

This is not consistent with the semantics of std::map, which returns an iterator to the whole element (the key-value pair), not the value alone.

std::map doesn't have find_ptr().

IMO the wrapper is useful every time you use a map like container.

In either case, find_ptr can be provided as an (overloaded) function, no need to have as a built-in member function. Thus my reluctance to address your request.

Can it? I can't (easily) select another overload for containers (like multi_index) that don't have a pair value_type.

My find_ptr() for std::map (and std::unordered_map, boost::ptr_map, etc):

template <class T, class U>
typename T::value_type::second_type* find_ptr(T& c, U v)
{
	typename T::iterator i = c.find(v);
	return i == c.end() ? NULL : &i->second;
}

template <class T, class U>
const typename T::value_type::second_type* find_ptr(const T& c, U v)
{
	typename T::const_iterator i = c.find(v);
	return i == c.end() ? NULL : &i->second;
}

template <class T, class U>
typename T::value_type::second_type find_ptr2(T& c, U v)
{
	typename T::iterator i = c.find(v);
	return i == c.end() ? NULL : i->second;
}

template <class T, class U>
const typename T::value_type::second_type find_ptr2(const T& c, U v)
{
	typename T::const_iterator i = c.find(v);
	return i == c.end() ? NULL : i->second;
}

comment:8 by Olaf van der Spek <olafvdspek@…>, 11 years ago

Look at http://www.boost.org/doc/libs/1_47_0/libs/multi_index/example/bimap.cpp for example.

dictionary::iterator it=get<from>(d).find(word);
  if(it!=d.end()){
    std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
  }
  1. Shouldn't it be get<from>(d).end()?
  2. You're not using it->first.

With bimaps though, you'd probably want to return a ptr to the pair.

in reply to:  7 ; comment:9 by Joaquín M López Muñoz, 11 years ago

Replying to Olaf van der Spek <olafvdspek@…>:

Replying to joaquin:

Why a pointer to second?

Because the key is known already.

This is not consistent with the semantics of std::map, which returns an iterator to the whole element (the key-value pair), not the value alone.

std::map doesn't have find_ptr().

Of course, but it has find(), which I understand you're copying semantics from, except that you return a pointer (null if no element was found) rather than an iterator (pointing to end if no element was found.)

IMO the wrapper is useful every time you use a map like container.

In either case, find_ptr can be provided as an (overloaded) function, no need to have as a built-in member function. Thus my reluctance to address your request.

Can it? I can't (easily) select another overload for containers (like multi_index) that don't have a pair value_type.

multi_index_containers don't sport a notion of second_type. But you can use the same wrapper as you're currently doing with std::set. Remember this conversarion began with your request for a member function returning a value_type* (not a pointer to the second part of the value.)

What problems are you having with defining an overload for multi_index_containers?

in reply to:  8 comment:10 by Joaquín M López Muñoz, 11 years ago

Replying to Olaf van der Spek <olafvdspek@…>:

Look at http://www.boost.org/doc/libs/1_47_0/libs/multi_index/example/bimap.cpp for example.

dictionary::iterator it=get<from>(d).find(word);
  if(it!=d.end()){
    std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
  }
  1. Shouldn't it be get<from>(d).end()?

Not strictly necessary: if you don't specify the index it's as if you're using the first one.

  1. You're not using it->first.

So? I'm not getting your point.

in reply to:  9 comment:11 by Olaf van der Spek <olafvdspek@…>, 11 years ago

Replying to joaquin:

Of course, but it has find(), which I understand you're copying semantics from, except that you return a pointer (null if no element was found) rather than an iterator (pointing to end if no element was found.)

True. Ideally I'd like to have find_ptr() for all containers that have a find().

IMO the wrapper is useful every time you use a map like container.

In either case, find_ptr can be provided as an (overloaded) function, no need to have as a built-in member function. Thus my reluctance to address your request.

Can it? I can't (easily) select another overload for containers (like multi_index) that don't have a pair value_type.

multi_index_containers don't sport a notion of second_type.

Right

But you can use the same wrapper as you're currently doing with std::set. Remember this conversarion began with your request for a member function returning a value_type* (not a pointer to the second part of the value.)

I don't have one yet.

What problems are you having with defining an overload for multi_index_containers?

I could easily define one with a different name, but I've no idea what enable_if code to use for automatic overload selection.

Not strictly necessary: if you don't specify the index it's as if you're using the first one.

True, but now the code assumes from is the first index.

Note: See TracTickets for help on using tickets.