[multi_index] iterating over keys and "extracting" key extractors

Q1: Is there a builtin in way in MI to iterate over keys rather than elements? I.e. the iterator's value type will be that of the key, not the element. Q2: Is there a way to obtain the type of key extractors given a multi index container? (it is related to Q1, as this sort of a thing could be passed to boost::transform iterator to obtain an alternative answer for Q1) An example is in order: struct Foo { int id; sting name; }; using namespace boost::multi_index; typedef multi_index_container< Foo, indexed_by< ordered_unique< member< Foo, int, &Foo::id > >, ordered_unique< member< Foo, string, &Foo::name > >
MFoo;
MFoo foos; // .. populate // Now, we want to iterate over sorted name's only, for e.g: auto beg = answer_to_Q1(foos).begin(); auto end = answer_to_Q1(foos).end(); std::copy( beg, end, ostream_iterator<string>(cout, " ") ); // Continuing the example for Q2: auto aFunctorThatExtractsFooName = answer_to_Q2<M>::type(); auto beg = make_transform_iterator( M.get<1>.cbegin(), aFunctorThatExtractsFooName ); auto end = make_transform_iterator( M.get<1>.cend(), aFunctorThatExtractsFooName ); std::copy( beg, end, ostream_iterator<string>(cout, " ") ); Thanks! Nick

Nick Stokes <randomaccessiterator <at> gmail.com> writes:
Q1: Is there a builtin in way in MI to iterate over keys rather than elements? I.e. the iterator's value type will be that of the key, not the element.
No, there's none. Some iterator adaption is needed as you mention below.
Q2: Is there a way to obtain the type of key extractors given a multi index container? (it is related to Q1, as this sort of a thing could be passed to boost::transform iterator to obtain an alternative answer for Q1)
auto beg=boost::make_transform_iterator( foos.get<1>().begin(),foos.get<1>().key_extractor()), end=boost::make_transform_iterator( foos.get<1>().end(),foos.get<1>().key_extractor()); std::copy( beg,end,std::ostream_iterator<std::string>(std::cout," ")); Joaquín M López Muñoz Telefónica

Thanks Joaquín On Wed, Mar 18, 2015 at 3:45 PM, Joaquin M Lopez Munoz <joaquin@tid.es> wrote:
Nick Stokes <randomaccessiterator <at> gmail.com> writes:
Q1: Is there a builtin in way in MI to iterate over keys rather than elements? I.e. the iterator's value type will be that of the key, not the element.
No, there's none. Some iterator adaption is needed as you mention below.
Q2: Is there a way to obtain the type of key extractors given a multi index container? (it is related to Q1, as this sort of a thing could be passed to boost::transform iterator to obtain an alternative answer for Q1)
auto beg=boost::make_transform_iterator( foos.get<1>().begin(),foos.get<1>().key_extractor()), end=boost::make_transform_iterator( foos.get<1>().end(),foos.get<1>().key_extractor());
std::copy( beg,end,std::ostream_iterator<std::string>(std::cout," "));
Joaquín M López Muñoz Telefónica _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

There is a problem... I noticed, when used as follows with boost::range, for( string& s : foos.get<1>() | boost::adaptors::transformed( m.get<1>().key_extractor() ) ) ... Visual Studio 2012 generates an ugly warning " warning C4172: returning address of local variable or temporary", and compiles. It also compiles on clang and gcc (sorry for not being too specific with versions, modern ones). But this is suspicious enough so I poked around a little bit. Sure enough, the key_from_value (the return type of key_extractor()) is a functor which is like template< .. class Value .. > struct key_from_value { typedef Value result_type; // not Value& Value& operator()( Foo&.. ) const { .. } }; So isn't result_type being a non-reference type a problem here, given operator() is returning &? Regards, Nick On Thu, Mar 19, 2015 at 9:09 AM, Nick Stokes <randomaccessiterator@gmail.com
wrote:
Thanks Joaquín
On Wed, Mar 18, 2015 at 3:45 PM, Joaquin M Lopez Munoz <joaquin@tid.es> wrote:
Nick Stokes <randomaccessiterator <at> gmail.com> writes:
Q1: Is there a builtin in way in MI to iterate over keys rather than elements? I.e. the iterator's value type will be that of the key, not the element.
No, there's none. Some iterator adaption is needed as you mention below.
Q2: Is there a way to obtain the type of key extractors given a multi index container? (it is related to Q1, as this sort of a thing could be passed to boost::transform iterator to obtain an alternative answer for Q1)
auto beg=boost::make_transform_iterator( foos.get<1>().begin(),foos.get<1>().key_extractor()), end=boost::make_transform_iterator( foos.get<1>().end(),foos.get<1>().key_extractor());
std::copy( beg,end,std::ostream_iterator<std::string>(std::cout," "));
Joaquín M López Muñoz Telefónica _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

... forgot to add, if I use a custom functor which does include the & in result_type, like: struct FooName { typedef const string& result_type; result_type operator()(const Foo& f) const { return f.name;} }; in the same ranged for as above: for( string& s : foos.get<1>() | boost::adaptors::transformed( FooName() ) ) .. then there is no warning from the compiler. On Thu, Mar 19, 2015 at 2:17 PM, Nick Stokes <randomaccessiterator@gmail.com
wrote:
There is a problem... I noticed, when used as follows with boost::range,
for( string& s : foos.get<1>() | boost::adaptors::transformed( m.get<1>().key_extractor() ) ) ...
Visual Studio 2012 generates an ugly warning " warning C4172: returning address of local variable or temporary", and compiles. It also compiles on clang and gcc (sorry for not being too specific with versions, modern ones). But this is suspicious enough so I poked around a little bit. Sure enough, the key_from_value (the return type of key_extractor()) is a functor which is like
template< .. class Value .. > struct key_from_value { typedef Value result_type; // not Value&
Value& operator()( Foo&.. ) const { .. }
};
So isn't result_type being a non-reference type a problem here, given operator() is returning &?
Regards, Nick
On Thu, Mar 19, 2015 at 9:09 AM, Nick Stokes < randomaccessiterator@gmail.com> wrote:
Thanks Joaquín
On Wed, Mar 18, 2015 at 3:45 PM, Joaquin M Lopez Munoz <joaquin@tid.es> wrote:
Nick Stokes <randomaccessiterator <at> gmail.com> writes:
Q1: Is there a builtin in way in MI to iterate over keys rather than elements? I.e. the iterator's value type will be that of the key, not the element.
No, there's none. Some iterator adaption is needed as you mention below.
Q2: Is there a way to obtain the type of key extractors given a multi index container? (it is related to Q1, as this sort of a thing could be passed to boost::transform iterator to obtain an alternative answer for Q1)
auto beg=boost::make_transform_iterator( foos.get<1>().begin(),foos.get<1>().key_extractor()), end=boost::make_transform_iterator( foos.get<1>().end(),foos.get<1>().key_extractor());
std::copy( beg,end,std::ostream_iterator<std::string>(std::cout," "));
Joaquín M López Muñoz Telefónica _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Sorry for being vague about versions. This was with Boost 1.49. Both Visual Studio 2012 and 2013 generates the warning. Clang 3.5.0 and g++ 4.7.2 do not. They all compile fine at the end. Also I just tried with Boost 1.56. There is no warning in either compiler! Strangely, the result_type typedef in key extractor is still non-& in this version. Perhaps Boost.Range changed... Any explanation of what may have changed and why not having a & in result_type works would be greatly appreciated. Thanks many, On Thu, Mar 19, 2015 at 2:20 PM, Nick Stokes <randomaccessiterator@gmail.com
wrote:
... forgot to add, if I use a custom functor which does include the & in result_type, like:
struct FooName { typedef const string& result_type; result_type operator()(const Foo& f) const { return f.name;} };
in the same ranged for as above:
for( string& s : foos.get<1>() | boost::adaptors::transformed( FooName() ) ) ..
then there is no warning from the compiler.
On Thu, Mar 19, 2015 at 2:17 PM, Nick Stokes < randomaccessiterator@gmail.com> wrote:
There is a problem... I noticed, when used as follows with boost::range,
for( string& s : foos.get<1>() | boost::adaptors::transformed( m.get<1>().key_extractor() ) ) ...
Visual Studio 2012 generates an ugly warning " warning C4172: returning address of local variable or temporary", and compiles. It also compiles on clang and gcc (sorry for not being too specific with versions, modern ones). But this is suspicious enough so I poked around a little bit. Sure enough, the key_from_value (the return type of key_extractor()) is a functor which is like
template< .. class Value .. > struct key_from_value { typedef Value result_type; // not Value&
Value& operator()( Foo&.. ) const { .. }
};
So isn't result_type being a non-reference type a problem here, given operator() is returning &?
Regards, Nick
On Thu, Mar 19, 2015 at 9:09 AM, Nick Stokes < randomaccessiterator@gmail.com> wrote:
Thanks Joaquín
On Wed, Mar 18, 2015 at 3:45 PM, Joaquin M Lopez Munoz <joaquin@tid.es> wrote:
Nick Stokes <randomaccessiterator <at> gmail.com> writes:
Q1: Is there a builtin in way in MI to iterate over keys rather than elements? I.e. the iterator's value type will be that of the key, not the element.
No, there's none. Some iterator adaption is needed as you mention below.
Q2: Is there a way to obtain the type of key extractors given a multi index container? (it is related to Q1, as this sort of a thing could be passed to boost::transform iterator to obtain an alternative answer for Q1)
auto beg=boost::make_transform_iterator( foos.get<1>().begin(),foos.get<1>().key_extractor()), end=boost::make_transform_iterator( foos.get<1>().end(),foos.get<1>().key_extractor());
std::copy( beg,end,std::ostream_iterator<std::string>(std::cout," "));
Joaquín M López Muñoz Telefónica _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Nick Stokes <randomaccessiterator <at> gmail.com> writes:
Sorry for being vague about versions. This was with Boost 1.49. Both Visual Studio 2012 and 2013 generates the warning. Clang 3.5.0 and g++ 4.7.2 do not. They all compile fine at the end.
Also I just tried with Boost 1.56. There is no warning in either compiler! Strangely, the result_type typedef in key extractor is still non-& in this version. Perhaps Boost.Range changed...
Please don't top-post: http://www.boost.org/community/policy.html#quoting Thank you! So, to sum up the top-posted chain of posts of yours, boost::multi_index::member<Class,Type,PtrToMember> publicizes its result type as typedef Type result_type; yet its call operator overloads return Type& or const Ttype&, and this results in some warnings in VS 12 / Boost 1.49 when used in combination with boost::adaptors::transform. So, whatever the problem is, it does not belong in Boost.MultiIndex, since member merely defines result_type in accordance with the requirements of the Key Extractor model: http://www.boost.org/libs/multi_index/doc/reference/ key_extraction.html#key_extractors I mean, defining result_type in whatever way (or not defining it at all) is not an error per se; it is Boost.Range assumptions on this typedef that might be problematic. Unfortunately, the documentation for boost::adaptors::tranform(rng,fun) http://www.boost.org/libs/range/doc/html/range/reference/ adaptors/reference/transformed.html do not mention what the requirements on fun are, whether it is mandatory that a result_type be present and how this is handled by Boost.Range. I suggest you initiate a new discussion with [range] in the subject line showing the problem you found. I suspect this is related to boost:result_of http://www.boost.org/libs/utility/utility.htm#result_of which Boost.Range seems to use internally, but only the author can tell. Also, if the problem does not show in Boost 1.56 you might be encouraged to simply upgrade and move on. Joaquín M López Muñoz Telefónica
participants (2)
-
Joaquin M Lopez Munoz
-
Nick Stokes