pointer to reference adaptor

Discussion in 'C++' started by Stanislaw Salik, Jul 30, 2004.

  1. Hi,

    Lets suppose we want to use generic algotithms on collections of
    pointers (both raw and smart). For example, we want to sort a vector of
    (smart)pointers. We need a comparator that will take two pointers and
    return a bool.

    std::vector<std::string *> v;
    std::sort(v.begin(), v.end(), std::less<int>());

    The code above will noc compile, since std::less<std::string>() object
    takes two strings, while we have pointers to std::string. So we need an
    adaptor.

    template <class T, class U>
    struct pointer_to_ref
    {
    typedef T argument_type;
    typedef U result_type;

    inline
    result_type & operator() (argument_type obj)
    {
    return *obj;
    }
    };

    std::vector<int *> v;
    std::sort(v.begin(), v.end(),
    boost::bind(std::less<string>(),
    boost::bind (pointer_to_ref<std::string*, std::string>(),_1),
    boost::bind (pointer_to_ref<std::string*, std::string>(),_2)));

    And the code will just work fine.

    And here goes my question. Since there are so many places where
    pointer_to_ref (and pointer_to_value probably) would be useful, is there
    any standard class that does the same thing?

    For example, for smart pointers i can use
    &collection_type::value_type::eek:perator* as an adaptor. But what if i
    wanted to make code more generic and working with raw pointers too?

    Regards,
    Stanislaw
     
    Stanislaw Salik, Jul 30, 2004
    #1
    1. Advertising

  2. "Stanislaw Salik" <> wrote in message
    news:cecujk$boi$...
    > Hi,
    >
    > Lets suppose we want to use generic algotithms on collections of
    > pointers (both raw and smart). For example, we want to sort a vector

    of
    > (smart)pointers. We need a comparator that will take two pointers

    and
    > return a bool.


    <snip>

    > template <class T, class U>
    > struct pointer_to_ref
    > {
    > typedef T argument_type;
    > typedef U result_type;
    >
    > inline
    > result_type & operator() (argument_type obj)
    > {
    > return *obj;
    > }
    > };


    > And here goes my question. Since there are so many places where
    > pointer_to_ref (and pointer_to_value probably) would be useful, is

    there
    > any standard class that does the same thing?


    First, for the example you gave -- which is a common situation -- you
    should be able to use indirect_iterators
    (http://www.boost.org/libs/iterator/doc/indirect_iterator.html)

    Second, I don't think it's necessary to have two template parameters.
    You should be able to calculate the result type given the argument
    type (see http://www.boost.org/boost/pointee.hpp.)

    Jonathan
     
    Jonathan Turkanis, Jul 30, 2004
    #2
    1. Advertising

  3. Stanislaw Salik, Jul 30, 2004
    #3
  4. Thanks for the information.

    Jonathan Turkanis wrote:

    > First, for the example you gave -- which is a common situation -- you
    > should be able to use indirect_iterators
    > (http://www.boost.org/libs/iterator/doc/indirect_iterator.html)


    The indirect_iterator adaptor works fine. However, the resulting
    algorithm is a bit different. With indirect_iterator, std::sort works on
    objects (in this case integers), while the approach with
    pointer_to_reference adaptors works on (smart)pointers.

    In the example1.cpp below outputs

    vect: 8 0 5 9 1 6 3 4 7 2
    copy: 0 1 2 3 4 5 6 7 8 9
    vect: 0 1 2 3 4 5 6 7 8 9
    copy: 0 1 2 3 4 5 6 7 8 9


    vect: 6 1 7 4 2 0 8 5 9 3
    copy: 0 1 2 3 4 5 6 7 8 9
    vect: 0 1 2 3 4 5 6 7 8 9
    copy: 5 1 4 9 3 7 0 2 6 8

    Notice that the copy becomes permuted while the original was sorted.

    Is there a way to use indirect_iterator in such way that sort replaces
    pointers instead of pointed values?

    Jonathan Turkanis wrote:

    > Second, I don't think it's necessary to have two template parameters.
    > You should be able to calculate the result type given the argument
    > type (see http://www.boost.org/boost/pointee.hpp.)


    This makes the code a bit cleaner. Is there a way to create adaptor
    object straight from the pointee<> template? Or is it still necessary to
    declare structure that does the trick?

    Regards,
    Stanislaw

    example1.cpp

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <vector>

    #include <stdlib.h>

    #include <boost/iterator/indirect_iterator.hpp>
    #include <boost/bind.hpp>

    template <class T>
    struct pointer_to_ref
    {
    typedef T argument_type;
    typedef typename boost::pointee<T>::type & result_type;

    inline
    result_type operator() (argument_type obj)
    {
    return *obj;
    }
    };

    struct counter
    {
    typedef int* result_type;

    counter () :n (0) {}
    result_type operator() () { return new int (n++); }

    int n;
    };

    typedef std::vector<int *> vector_t;


    int
    main ()
    {
    srand(time(0));

    vector_t v;

    std::generate_n (std::back_insert_iterator<vector_t>(v), 10,
    counter());

    vector_t w (v);

    std::random_shuffle (v.begin(), v.end());

    std::cout << "vect: ";
    std::copy (boost::make_indirect_iterator(v.begin()),
    boost::make_indirect_iterator(v.end()),
    std::eek:stream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "copy: ";
    std::copy (boost::make_indirect_iterator(w.begin()),
    boost::make_indirect_iterator(w.end()),
    std::eek:stream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    std::sort (v.begin(),
    v.end(),
    boost::bind(std::less<int>(),

    boost::bind(pointer_to_ref<vector_t::value_type>(), _1),

    boost::bind(pointer_to_ref<vector_t::value_type>(), _2)));

    std::cout << "vect: ";
    std::copy (boost::make_indirect_iterator(v.begin()),
    boost::make_indirect_iterator(v.end()),
    std::eek:stream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "copy: ";
    std::copy (boost::make_indirect_iterator(w.begin()),
    boost::make_indirect_iterator(w.end()),
    std::eek:stream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    return 0;
    }



    example2.cpp:

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <vector>

    #include <stdlib.h>

    #include <boost/iterator/indirect_iterator.hpp>


    struct counter
    {
    typedef int* result_type;

    counter () :n (0) {}
    result_type operator() () { return new int (n++); }

    int n;

    };

    typedef std::vector<int *> vector_t;

    int
    main ()
    {
    srand(time(0));

    vector_t v;

    std::generate_n (std::back_insert_iterator<vector_t>(v), 10,
    counter());

    vector_t w (v);

    std::random_shuffle (v.begin(), v.end());

    std::cout << "vect: ";
    std::copy (boost::make_indirect_iterator(v.begin()),
    boost::make_indirect_iterator(v.end()),
    std::eek:stream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "copy: ";
    std::copy (boost::make_indirect_iterator(w.begin()),
    boost::make_indirect_iterator(w.end()),
    std::eek:stream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    std::sort (boost::make_indirect_iterator(v.begin()),
    boost::make_indirect_iterator(v.end()),
    std::less<int>());

    std::cout << "vect: ";
    std::copy (boost::make_indirect_iterator(v.begin()),
    boost::make_indirect_iterator(v.end()),
    std::eek:stream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "copy: ";
    std::copy (boost::make_indirect_iterator(w.begin()),
    boost::make_indirect_iterator(w.end()),
    std::eek:stream_iterator<int>(std::cout, " "));
    std::cout << std::endl;

    return 0;
    }
     
    Stanislaw Salik, Jul 30, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?S2VudCBL?=

    Creating a SQL adaptor object on a remote server

    =?Utf-8?B?S2VudCBL?=, Apr 1, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    332
    =?Utf-8?B?S2VudCBL?=
    Apr 1, 2004
  2. Sripathy Ramesh
    Replies:
    0
    Views:
    587
    Sripathy Ramesh
    Nov 25, 2003
  3. Scott Smedley

    A different kind of adaptor iterator

    Scott Smedley, Dec 5, 2003, in forum: C++
    Replies:
    4
    Views:
    438
    Scott Smedley
    Dec 7, 2003
  4. Matthias

    Dereferencing adaptor?

    Matthias, Feb 7, 2005, in forum: C++
    Replies:
    2
    Views:
    332
    Matthias
    Feb 8, 2005
  5. Matthias Kaeppler

    Dereference Adaptor

    Matthias Kaeppler, Feb 27, 2005, in forum: C++
    Replies:
    3
    Views:
    479
    Kurt Krueckeberg
    Feb 28, 2005
Loading...

Share This Page