How to erase type from output iterators as std::insert_iterator and std::back_insert_iterator? Is it possible to use boost any_iterator to do so?
#include <boost/range.hpp>
#include <boost/range/detail/any_iterator.hpp>
#include <vector>
typedef boost::range_detail::any_iterator<
int, boost::incrementable_traversal_tag, int &, std::ptrdiff_t > It;
int main()
{
std::vector<int> v;
It outIt( v.begin() ); // compiles
It inserter( std::back_inserter(v) ); // does not compile
return 0;
}
any_iterator is not designed for use with output iterators, which is what back_insert_iterator is (or, for that matter, input iterators).
back_insert_iterator is defined to inherit from iterator<output_iterator_tag, void, void, void, void> i.e. its value_type, reference_type, distance_type and pointer_type are all void, but any_iterator expects to be able to indirect through its backing iterator to a non-void value. Perhaps it would be better named any_value_iterator; but then it is a detail class template.
So I implemented my own one using Boost.
#include <boost/function_output_iterator.hpp>
#include <boost/function.hpp>
template < class T >
class AnyInserter : public boost::function_output_iterator< boost::function< void ( const T & value ) > >
{
private:
typedef typename boost::function_output_iterator< boost::function< void ( const T & value ) > > BaseType;
template < class OutIt > struct Insert
{
Insert( OutIt it ) : m_it(it) {}
void operator () ( const T & value ) { m_it++ = value; }
OutIt m_it;
};
public:
template < class OutIt >
explicit AnyInserter( const OutIt & it ) : BaseType( Insert< OutIt >(it) ) {}
};
template < class OutIt >
inline AnyInserter< typename OutIt::container_type::value_type >
makeAnyInserter( const OutIt & it )
{
return AnyInserter< typename OutIt::container_type::value_type >(it);
}
Related
I am writing template classes for de/serialization of stl containers.
Let's say I want to serialize a set<int>. I have a base serialisation class and the following template:
template<typename T>class serialiser;
template<>class serialiser<int>:public serialisation<int>{
public:
void serialise ( int t );
};
To serialize the set, I have:
template<typename T>class Container_serialiser:public serialisation<T>{
public:
void serialise ( T t );
private:
/* Notice that I must declare a serialiser.
*/
serialiser<typename T :: value_type>value_serialiser;
};
template<typename T>void Container_serialiser<T>::serialise ( T t ){
for(typename T :: const_iterator t_iterator = t . begin ( );t_iterator != t . end ( );++ t_iterator){
value_serialiser . serialise ( * t_iterator );
}
}
This only works for containers with elements that do not themselves comprise containers.
The Problem
What if I want to serialize a map<int,set<int> >?
Since each element's type is pair<int,set<int> >, I need the following class:
template<>class serialiser<pair<int,set<int> > >:public serialisation<pair<int,set<int> > >{
public:
void serialise ( const pair<int,set<int> >t );
private:
serialiser<int>t_first_serialiser;
/* Notice that I must declare a Container_serialiser.
*/
Container_serialiser<set<int> >t_second_serialiser;
};
However, Container_serialiser requires serialiser<T> to be a complete type. Thus, it cannot be defined until after the above class. Likewise, the above class requires Container_serialiser<T> to be a complete type and cannot be defined before it.
The compiler gives the following error:
prog.cpp: In instantiation of 'class Container_serialiser<std::map<int, std::set<int> > >':
prog.cpp:73:44: required from here
prog.cpp:40:39: error: 'Container_serialiser<T>::value_serialiser' has incomplete type
serialiser<typename T :: value_type>value_serialiser;
^
prog.cpp:25:27: note: declaration of 'class serialiser<std::pair<const int, std::set<int> > >'
template<typename T>class serialiser;
Problem Code
#include <iostream>
#include <map>
#include <set>
#include <utility>
using std :: cout;
using std :: map;
using std :: set;
using std :: make_pair;
using std :: pair;
template<typename T>class serialisation{
public:
virtual ~serialisation ( );
protected:
virtual void serialise ( const T t ) = 0;
};
template<typename T>serialisation<T> :: ~serialisation ( ){
}
template<typename T>class serialiser;
template<>class serialiser<int>:public serialisation<int>{
public:
void serialise ( const int t );
};
void serialiser<int>:: serialise ( const int t ){
cout << t << '\n';
}
template<typename T>class Container_serialiser:public serialisation<T>{
public:
void serialise ( const T t );
private:
serialiser<typename T :: value_type>value_serialiser;
};
template<typename T>void Container_serialiser<T>:: serialise ( const T t ){
for(typename T :: const_iterator t_iterator = t . begin ( );t_iterator != t . end ( );++ t_iterator){
value_serialiser . serialise ( * t_iterator );
}
}
template<>class serialiser<pair<int,set<int> > >:public serialisation<pair<int,set<int> > >{
public:
void serialise ( const pair<int,set<int> >t );
private:
serialiser<int>t_first_serialiser;
Container_serialiser<set<int> >t_second_serialiser;
};
void serialiser<pair<int,set<int> > >:: serialise ( const pair<int,set<int> >t ){
t_first_serialiser . serialise ( t . first );
t_second_serialiser . serialise ( t . second );
}
int main ( ){
set<int>t;
t . insert ( 2 );
t . insert ( 3 );
Container_serialiser<set<int> >t_serialiser;
t_serialiser . serialise ( t );
map<int,set<int> >u;
u . insert ( make_pair ( 5,t ) );
u . insert ( make_pair ( 7,t ) );
Container_serialiser<map<int,set<int> > >u_serialiser;
u_serialiser . serialise ( u );
}
Ideone
A Hack
I can make this work by writing four templates:
serialiser0<T> for all T that are not containers and do not comprise containers
Container_serialiser0<T> for all T whose value_type is the argument of a serialiser0<T>
serialiser1<T> for all T that are not containers but comprise containers of elements that themselves do not comprise containers
Container_serialiser1<T> for all T whose value_type is the argument of a serialiser1<T>
This design is repetitive, confusing, and has to be extended manually for each new level of containers. Is there a better pattern?
Unfortunately, due to the project I am working on, I must avoid external dependencies such as boost.serialization even at the cost of taking a performance hit and write for the C++98 standard.
Hack Code
#include <iostream>
#include <map>
#include <set>
#include <utility>
using std :: cout;
using std :: map;
using std :: set;
using std :: make_pair;
using std :: pair;
template<typename T>class serialisation{
public:
virtual ~serialisation ( );
protected:
virtual void serialise ( const T t ) = 0;
};
template<typename T>serialisation<T> :: ~serialisation ( ){
}
template<typename T>class serialiser0;
template<>class serialiser0<int>:public serialisation<int>{
public:
void serialise ( const int t );
};
void serialiser0<int>:: serialise ( const int t ){
cout << t << '\n';
}
template<typename T>class Container_serialiser0:public serialisation<T>{
public:
void serialise ( const T t );
private:
serialiser0<typename T :: value_type>value_serialiser;
};
template<typename T>void Container_serialiser0<T>:: serialise ( const T t ){
for(typename T :: const_iterator t_iterator = t . begin ( );t_iterator != t . end ( );++ t_iterator){
value_serialiser . serialise ( * t_iterator );
}
}
template<typename T>class serialiser1;
template<>class serialiser1<pair<const int,set<int> > >:public serialisation<pair<int,set<int> > >{
public:
void serialise ( const pair<int,set<int> >t );
private:
serialiser0<int>t_first_serialiser;
Container_serialiser0<set<int> >t_second_serialiser;
};
void serialiser1<pair<const int,set<int> > >:: serialise ( const pair<int,set<int> >t ){
t_first_serialiser . serialise ( t . first );
t_second_serialiser . serialise ( t . second );
}
/* This is the same as Container_serialiser0!
*/
template<typename T>class Container_serialiser1:public serialisation<T>{
public:
void serialise ( const T t );
private:
serialiser1<typename T :: value_type>value_serialiser;
};
template<typename T>void Container_serialiser1<T>:: serialise ( const T t ){
for(typename T :: const_iterator t_iterator = t . begin ( );t_iterator != t . end ( );++ t_iterator){
value_serialiser . serialise ( * t_iterator );
}
}
int main ( ){
set<int>t;
t . insert ( 2 );
t . insert ( 3 );
Container_serialiser0<set<int> >t_serialiser;
t_serialiser . serialise ( t );
map<int,set<int> >u;
u . insert ( make_pair ( 5,t ) );
u . insert ( make_pair ( 7,t ) );
Container_serialiser1<map<int,set<int> > >u_serialiser;
u_serialiser . serialise ( u );
}
Ideone
(I must admit that I had forgotten about this question.)
Thanks to #michael-gopshtein's comment, I eventually stumbled upon partial template specialization, which solves this problem quite well. Note that I must use both template <typename SerialisedType> class Serialiser and template <typename SerialisedType> inline void serialise(const SerialisedType &x). The function itself cannot be partially-specialized, but most specializations of Serialiser::serialise depend upon a general call to ::serialise.
To serialize a std::map<int, std::set<int>>, I would write the following:
#include <map>
#include <set>
#include <utility>
// For the sake of having a MWE, I'll just write int-s to stdout.
#include <iostream>
template <typename SerialisedType> class Serialiser;
template <typename SerialisedType>
inline void serialise(const SerialisedType &x) {
Serialiser<SerialisedType>::serialise(x);
}
template <> class Serialiser<int> {
public:
inline static void serialise(const int &x);
};
template <typename Key> class Serialiser<std::set<Key>> {
public:
inline static void serialise(const std::set<Key> &x);
};
template <typename T1, typename T2> class Serialiser<std::pair<T1, T2>> {
public:
inline static void serialise(const std::pair<T1, T2> &x);
};
template <typename Key, typename T>
class Serialiser<std::map<Key, T>> {
public:
inline static void serialise(const std::map<Key, T> &x);
};
void Serialiser<int>::serialise(const int &x) {
std::cout << x << "\n";
}
template <typename Key>
void Serialiser<std::set<Key>>::serialise(const std::set<Key> &x) {
{
const typename std::set<Key>::const_iterator x_cend = x.cend();
for (typename std::set<Key>::const_iterator x_iterator = x.cbegin();
x_iterator != x_cend; ++x_iterator)
::serialise(*x_iterator);
}
}
template <typename T1, typename T2>
void Serialiser<std::pair<T1, T2>>::serialise(const std::pair<T1, T2> &x) {
::serialise(x.first);
::serialise(x.second);
}
template <typename Key, typename T>
void Serialiser<std::map<Key, T>>::serialise(const std::map<Key, T> &x) {
{
const typename std::map<Key, T>::const_iterator x_cend = x.cend();
for (typename std::map<Key, T>::const_iterator x_iterator = x.cbegin();
x_iterator != x_cend; ++x_iterator)
::serialise(*x_iterator);
}
}
int main() {
std::map<int, std::set<int>> u {
{5, {2, 3}},
{7, {2, 3}}
};
serialise(u);
}
Output:
5
2
3
7
2
3
I am having problems implementing the specialization of a class template that uses template template parameters. For example, I would like to write a class that is used for sorting:
template <template <typename, typename...> class container_type> struct SortTraits {
template <class comparator_type>
static void sort(container_type<size_t> &front, comparator_type comp) {
std::sort(front.begin(), front.end(), comp);
}
};
template <> struct SortTraits<std::list> {
template <class T, class comparator_type>
static void sort(std::list<T> &front, comparator_type comp) {
front.sort(comp);
}
};
Then I would call this as follows:
struct MyFunctor {
bool operator()( const size_t& a, const size_t& b ) const {
return a>b;
}
};
//! Alias template used for the type of container used to store a front
template <class T> using container_template = std::list<T>;
int main(int argc, char *argv[]) {
//! Concrete type for a front
typedef container_template<size_t> front_type;
front_type myContainer = {3,5,2,6,3,6,7};
MyFunctor mySortFunctor;
SortTraits<container_template>::sort(myContainer, mySortFunctor);
for (auto it = myContainer.begin(); it != myContainer.end(); ++it)
cout<<" "<<*it;
cout<<endl;
exit(0);
}
I use the specialization for the list as I would like to call the sort function that the std::list implements. Yet, this code doesn't work. Why the template specialization is not being found?
The error I get is:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/algorithm:3772:40: error: invalid operands
to binary expression ('std::__1::__list_iterator' and 'std::__1::__list_iterator')
difference_type __len = __last - __first;
~~~~~~ ^ ~~~~~~~
And it's because it's not finding the specialization.
Why bother with the traits class and the partial specialization at all instead of simply overloading a sort function? As the saying goes, std::less is more. (Live at Coliru)
template <typename Container>
using less = std::less<
typename std::decay<
decltype(*std::declval<Container&>().begin())
>::type
>;
template<typename Container, typename Compare = less<Container>>
inline void sort(Container& container, Compare&& comp = {}) {
using std::begin;
using std::end;
std::sort(begin(container), end(container), std::forward<Compare>(comp));
}
template<typename... T, typename Compare = less<std::list<T...>>>
inline void sort(std::list<T...>& list, Compare&& comp = {}) {
list.sort(std::forward<Compare>(comp));
}
For that matter, a generic sort function that prefers member sort when it exists would save you the trouble of writing overloads at all (Live at Coliru):
namespace detail {
using std::begin;
using std::end;
template<typename Container, typename Compare>
inline void sort_(Container& container, Compare&& comp, ...) {
std::sort(begin(container), end(container), std::forward<Compare>(comp));
}
template<typename Container, typename Compare>
inline auto sort_(Container& container, Compare&& comp, int) ->
decltype(container.sort(std::forward<Compare>(comp))) {
return container.sort(std::forward<Compare>(comp));
}
template<typename Container, typename Compare = std::less<
typename std::decay<
decltype(*begin(std::declval<Container&>()))
>::type
>>
inline void sort(Container& container, Compare&& comp = {}) {
sort_(container, std::forward<Compare>(comp), 0);
}
} // namespace detail
using detail::sort;
Why not just use type parameters?:
template<typename CONTAINER>
struct SortTraits
{
template<typename COMPARATOR>
static void sort( CONTAINER& container , COMPARATOR comparator = std::less<> )
{
std::sort( std::begin( container ) , std::end( container ) , comparator );
}
};
template<typename T>
struct SortTraits<std::list<T>>
{
template<typename COMPARATOR>
static void sort( std::list<T>& list , COMPARATOR comparator )
{
list.sort( comparator );
}
};
namespace utils
{
template<typename CONTAINER , typename COMPARATOR>
void sort( CONTAINER& container , COMPARATOR comparator )
{
SortTraits<CONTAINER>::sort( container , comparator );
}
}
int main()
{
std::array<int,4> arr = { 1 , 2 , 3 , 4 };
std::list<int> list = { 1 , 2 , 3 , 4 };
std::vector<int> vec = { 1 , 2 , 3 , 4 };
utils::sort( arr );
utils::sort( list );
utils::sort( vec );
}
I am cutting my teeth at some template programming and I am very new to this. What I want to implement are a few CRTP classes that contain an STL container. Let class A{}; serve as an example for the (compile time) base class from which class B{}; and class C{}; are "derived" at compile time following the CRTP style.
Now both B and C will contain containers. For the purpose of the example let it be a std::vector and a std::set respectively. Now, I want to expose the iterators of these via a begin() and an end() function that exposes a forward iterator. However, I do not want to expose what is the exact container that is inside B and C and I want to define these functions for A, so that at call time the correct one for B and C get used.
Is this possible ? Right now my plan is to have a Iterator inner class for B as well as C that will contain the actual iterator of (a vector or a set as the case may be) and delegate the call to it. However this seems to be a lot of replicated glue code and I suspect there is a better option.
I have a couple of questions:
How do I declare the inner clases in A, B and C so that it plays well with CRTP. Do I need to replicate it for A, B and C ? Can it be an empty class in A and I mask them in B and C with specialized implementations ?
How can I expose the iterator with less glue and less duplication ?
I do not want to create dependencies with external libraries like boost and want to stick to std only. So I have to implement whatever extra I need myself. Thanks for all the help.
Expose the iterator too via CRTP:
template <typename T, typename Iter, typename ConstIter>
struct Base
{
Iter begin() { return static_cast<T*>(this)->begin(); }
Iter end() { return static_cast<T*>(this)->end(); }
ConstIter begin() const { return static_cast<const T*>(this)->begin(); }
ConstIter end() const { return static_cast<const T*>(this)->end(); }
};
struct B : Base<B, std::vector<int>::iterator, std::vector<int>::const_iterator>
{
std::vector<int>::iterator begin() { return container.begin(); }
...
private:
std::vector<int> container;
};
If you have more types to expose, then pass a traits class as a template argument to Base:
template <typename T, typename Traits>
struct Base
{
typename Traits::iterator begin() { ... }
...
};
// For this purpose, vector<int> makes a perfect traits class !
struct B : Base<B, std::vector<int> >
{
std::vector<int>::iterator begin() { ... }
...
};
// Here is an example function taking Base as argument
template <typename T, typename Traits>
void foo(const Base<T, Traits>& x)
{
typename Traits::iterator i = x.begin();
...
}
If I understood you corretcly, you are looking for something like this. Note, I made some simple constructor just to illustrate that it works. Also, your class A is mine class TWrapperBase, B - TWrapperB, C - TWrapperC. Another thing, you don't really need to have two derived classes for this particular example, but I assume your classes B and C are significantly different to justify it in your program.
EDIT: Forgot to increment lIterSet in the loop.
#include <vector>
#include <set>
#include <iostream>
template< typename PType, typename PContainer >
class TWrapperBase
{
public:
typedef PType TType;
typedef PContainer TContainer;
typedef typename TContainer::iterator TIterator;
protected:
TContainer mContainer;
public:
TWrapperBase( const TContainer& pOriginal ) :
mContainer( pOriginal )
{
}
TIterator begin( void )
{
return mContainer.begin();
}
TIterator end( void )
{
return mContainer.end();
}
};
template< typename PType, class PContainer = std::vector< PType > >
class TWrapperB : public TWrapperBase< PType, PContainer >
{
public:
TWrapperB( const TContainer& pOriginal ) :
TWrapperBase( pOriginal )
{
}
};
template< typename PType, class PContainer = std::set< PType > >
class TWrapperC : public TWrapperBase< PType, PContainer >
{
public:
TWrapperC( const TContainer& pOriginal ) :
TWrapperBase( pOriginal )
{
}
};
int main( void )
{
int lInit[] =
{
1, 2, 3
};
std::vector< int > lVec( lInit, lInit + 3 );
std::set< int > lSet( lInit, lInit + 3 );
TWrapperB< int > lB( lVec );
TWrapperC< int > lC( lSet );
std::vector< int >::iterator lIterVec = lB.begin();
std::set< int >::iterator lIterSet = lC.begin();
while( lIterVec < lB.end() )
{
std::cout << "vector: " << *lIterVec << " / set: " << *lIterSet << std::endl;
lIterVec++;
lIterSet++;
}
return 0;
}
Let's say I'd like to write an algorithm that prints the value of each element in a container. The container could be a Sequence or Associative container (e.g. std::vector or std::map). In the case of a sequence, the algorithm would print the value_type. In the case of an associative type, the algorithm would print the data_type. How can I write my algorithm (only once!) so that it works with either one? Pretend that the algorithm is complex and that I don't want to repeat it for both sequence/associative versions.
For example:
template <class Iterator>
void printSequence(Iterator begin, Iterator end)
{
for (Iterator it=begin; it!=end; ++it)
std::cout << *it;
}
template <class Iterator>
void printAssociative(Iterator begin, Iterator end)
{
for (Iterator it=begin; it!=end; ++it)
std::cout << it->second;
}
template <class Iterator>
void printEither(Iterator begin, Iterator end)
{
// ????
}
The difference that you have between your two function templates is not a difference between associative containers and sequences but a difference in the part of the type that is stored.
To clarify, std::set is an associative container but would work with your printSequence function; the problem with map is not the fact that it is associative, but that the value_type is a pair an you are only interested on the second part.
The simplest thing to do is to abstract the dereferencing operation.
E.g. used like this:
#include <map>
#include <vector>
template< class X, class Y >
void test( const std::map<X, Y>& mp )
{
printEither( mp.begin(), mp.end(), MakeMapDerefence( mp ) );
}
template< class Y >
void test( const std::vector<Y>& vec )
{
printEither( vec.begin(), vec.end(), MakeSimpleDereference( vec ) );
}
Defined like this (there's a fair bit of boiler plate that's probably a boost one-liner):
template< class ReferenceType, class IteratorType >
struct SimpleDereference
{
ReferenceType operator() ( IteratorType i ) const
{
return *i;
}
};
template< class ReferenceType, class IteratorType >
struct MapDereference
{
ReferenceType operator() ( IteratorType i ) const
{
return i->second;
}
};
// Helper template function to make an appropriate SimpleDerefence instance
template< class Container >
SimpleDereference< typename Container::const_reference
, typename Container::const_iterator >
MakeSimpleDereference( const Container& )
{
return SimpleDereference< typename Container::const_reference
, typename Container::const_iterator >();
}
// Helper template function to make an appropriate SimpleDerefence instance
template< class Container >
SimpleDereference< typename Container::reference
, typename Container::iterator >
MakeSimpleDereference( Container& )
{
return SimpleDereference< typename Container::reference
, typename Container::iterator >();
}
// Helper template function to make an appropriate MapDerefence instance
template< class Container >
MapDereference< const typename Container::mapped_type&
, typename Container::const_iterator >
MakeMapDerefence( const Container& )
{
return MapDereference< const typename Container::mapped_type&
, typename Container::const_iterator >();
}
// Helper template function to make an appropriate MapDerefence instance
template< class Container >
MapDereference< typename Container::mapped_type&
, typename Container::iterator >
MakeMapDereference( Container& )
{
return MapDereference< typename Container::mapped_type&
, typename Container::iterator >();
}
#include <iostream>
#include <ostream>
template <class Iterator, class Dereference> void printEither(Iterator begin, Iterator end, Dereference deref)
{
for (; begin != end; ++begin)
{
std::cout << deref(begin);
}
}
I've whipped up an iterator adapter based on Charles' answer. I'm posting it here in case anyone finds it useful:
#include <iostream>
#include <map>
#include <vector>
#include <boost/iterator/iterator_adaptor.hpp>
//------------------------------------------------------------------------------
template <class Iterator>
void print(Iterator begin, Iterator end)
{
for (Iterator it=begin; it!=end; ++it)
std::cout << *it << "\n";
}
//------------------------------------------------------------------------------
template <class BaseIterator>
class MapDataIterator :
public boost::iterator_adaptor<
MapDataIterator<BaseIterator>,
BaseIterator,
typename BaseIterator::value_type::second_type >
{
public:
typedef typename BaseIterator::value_type::second_type& reference;
MapDataIterator() {}
explicit MapDataIterator(BaseIterator base)
: MapDataIterator::iterator_adaptor_(base) {}
private:
friend class boost::iterator_core_access;
reference dereference() const
{return this->base_reference()->second;}
};
//------------------------------------------------------------------------------
int main()
{
std::vector<int> vec;
vec.push_back(31);
vec.push_back(41);
std::map<int,int> map;
map[31] = 41;
map[59] = 26;
typedef MapDataIterator< std::map<int,int>::iterator > DataIter;
print( vec.begin(), vec.end() );
print( DataIter(map.begin()), DataIter(map.end()) );
}
This solution has the added advantage that the algorithm need not be aware of how to dereference the iterators. It is also reusable for any existing algorithm that expects a "data sequence".
I'm surprised this little critter doesn't already exist in Boost.
HI,
I don't like posting compile problems, but I really can't figure this one out. Using this code:
#include <map>
#include <boost/iterator/transform_iterator.hpp>
using namespace std;
template <typename K, typename V>
struct get_value
{
const V& operator ()(std::pair<K, V> const& p) { return p.second; }
};
class test
{
typedef map<int, float> TMap;
TMap mymap;
public:
typedef get_value<TMap::key_type, TMap::value_type> F;
typedef boost::transform_iterator<F, TMap::iterator> transform_iterator;
transform_iterator begin()
{
return make_transform_iterator(mymap.begin(), F());
}
};
Getting this compile error:
transform_iterator.hpp(43) : error C2039: 'result_type' : is not a member of 'get_value<K,V>'
with
[
K=int,
V=std::pair<const int,float>
]
Can anyone explain why this isn't working? I'm using Visual Studio 7.0 with boost 1.36.0
Thanks.
Since you also asked for an explanation
The transform_iterator needs to know the return type of the function called in order to instantiate itself. This is determined via result_of (found in <boost/utility/result_of.hpp>
If you use a function object, you need to define a member result_type to specify the result type of the object. (since an object doesn't have a 'return type' as such)
If you would have used a regular function, result_of would be able to figure it out on his own, e.g.:
template <typename K, typename V>
const V & get_value(std::pair<K, V> const & p) { return p.second; }
class test
{
typedef map<int, float> TMap;
TMap mymap;
public:
typedef boost::function< const TMap::mapped_type & (const TMap::value_type &) > F;
typedef boost::transform_iterator<F, TMap::iterator> transform_iterator;
transform_iterator begin()
{
return boost::make_transform_iterator(mymap.begin(), &get_value< int, float >);
}
};
You'll have to inherit get_value from unary_function<const V&, std::pair<K, V> const&> to tell transform_iterator what the signature of get_value is.
// here is a working example:
#include <vector>
#include <iostream>
#include <boost/iterator/transform_iterator.hpp>
template <typename T, typename U>
const T& Get1st(const std::pair<T, U>& pair) { return pair.first; }
struct Bar {
using Pairs = std::vector<std::pair<int, char>>;
using Iter = boost::transform_iterator< decltype(&Get1st<int, char>), Pairs::const_iterator >;
void add(int i, char c) { _pairs.emplace_back(i, c); }
Iter begin() { return boost::make_transform_iterator(_pairs.begin(), &Get1st<int, char>); }
Iter end() { return boost::make_transform_iterator(_pairs.end(), &Get1st<int, char>); }
private:
Pairs _pairs;
};
int main() {
Bar bar;
bar.add(1, 'a');
bar.add(3, 'c');
bar.add(2, 'b');
for(const auto& i : bar) std::cout << i << " ";
std::cout << "\n";
return 0;
}
// outputs: 1, 3, 2