Fail to understand std::transform

Discussion in 'C++' started by Vijai Kalyan, Oct 12, 2006.

  1. Vijai Kalyan

    Vijai Kalyan Guest

    Hello,

    I am trying to use std::transform to take in a collection of strings,
    transform them and insert the result into an output container. So, I
    wrote something like this:

    std::wstring doSomething (std::wstring const& str)
    {
    // do something to copy of str and return new value
    }

    void foo ()
    {
    std::set<std::wstring> input;
    std::set<std::wstring> output;

    std::transform (input.begin(), input.end(), output.begin(),
    doSomething);
    }

    I stepped into the implementation of std::transform (on my platform)
    and it goes something like:-

    template<class _InIt,
    class _OutIt,
    class _Fn1> inline
    _OutIt transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)
    { // transform [_First, _Last) with _Func
    for (; _First != _Last; ++_First, ++_Dest)
    *_Dest = _Func(*_First);
    return (_Dest);
    }

    It looks like the

    *_Dest = _Func (*_First)

    would mean that transform expects the output objects to already exist.
    Is that right? I keep crashing at the assignment. Does std::transform
    require sequence containers with pre-reserved sizes?

    thanks,

    -vijai.
     
    Vijai Kalyan, Oct 12, 2006
    #1
    1. Advertising

  2. Vijai Kalyan

    Vijai Kalyan Guest

    Doh!

    The documentation says that the output range must be valid. THen the
    question becomes:-

    I got a bunch of objects. I have to transform them in some way and
    insert them into a destination. How would I do that?

    -vijai.


    Vijai Kalyan wrote:
    > Hello,
    >
    > I am trying to use std::transform to take in a collection of strings,
    > transform them and insert the result into an output container. So, I
    > wrote something like this:
    >
    > std::wstring doSomething (std::wstring const& str)
    > {
    > // do something to copy of str and return new value
    > }
    >
    > void foo ()
    > {
    > std::set<std::wstring> input;
    > std::set<std::wstring> output;
    >
    > std::transform (input.begin(), input.end(), output.begin(),
    > doSomething);
    > }
    >
    > I stepped into the implementation of std::transform (on my platform)
    > and it goes something like:-
    >
    > template<class _InIt,
    > class _OutIt,
    > class _Fn1> inline
    > _OutIt transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)
    > { // transform [_First, _Last) with _Func
    > for (; _First != _Last; ++_First, ++_Dest)
    > *_Dest = _Func(*_First);
    > return (_Dest);
    > }
    >
    > It looks like the
    >
    > *_Dest = _Func (*_First)
    >
    > would mean that transform expects the output objects to already exist.
    > Is that right? I keep crashing at the assignment. Does std::transform
    > require sequence containers with pre-reserved sizes?
    >
    > thanks,
    >
    > -vijai.
     
    Vijai Kalyan, Oct 12, 2006
    #2
    1. Advertising

  3. Vijai Kalyan

    Vijai Kalyan Guest

    Doh!

    The documentation says that the output range must be valid. THen the
    question becomes:-

    I got a bunch of objects. I have to transform them in some way and
    insert them into a destination. How would I do that?

    -vijai.


    Vijai Kalyan wrote:
    > Hello,
    >
    > I am trying to use std::transform to take in a collection of strings,
    > transform them and insert the result into an output container. So, I
    > wrote something like this:
    >
    > std::wstring doSomething (std::wstring const& str)
    > {
    > // do something to copy of str and return new value
    > }
    >
    > void foo ()
    > {
    > std::set<std::wstring> input;
    > std::set<std::wstring> output;
    >
    > std::transform (input.begin(), input.end(), output.begin(),
    > doSomething);
    > }
    >
    > I stepped into the implementation of std::transform (on my platform)
    > and it goes something like:-
    >
    > template<class _InIt,
    > class _OutIt,
    > class _Fn1> inline
    > _OutIt transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)
    > { // transform [_First, _Last) with _Func
    > for (; _First != _Last; ++_First, ++_Dest)
    > *_Dest = _Func(*_First);
    > return (_Dest);
    > }
    >
    > It looks like the
    >
    > *_Dest = _Func (*_First)
    >
    > would mean that transform expects the output objects to already exist.
    > Is that right? I keep crashing at the assignment. Does std::transform
    > require sequence containers with pre-reserved sizes?
    >
    > thanks,
    >
    > -vijai.
     
    Vijai Kalyan, Oct 12, 2006
    #3
  4. Vijai Kalyan

    Daniel T. Guest

    "Vijai Kalyan" <> wrote:

    > Hello,
    >
    > I am trying to use std::transform to take in a collection of strings,
    > transform them and insert the result into an output container. So, I
    > wrote something like this:
    >
    > std::wstring doSomething (std::wstring const& str)
    > {
    > // do something to copy of str and return new value
    > }
    >
    > void foo ()
    > {
    > std::set<std::wstring> input;
    > std::set<std::wstring> output;
    >
    > std::transform (input.begin(), input.end(), output.begin(),
    > doSomething);
    > }
    >
    > I stepped into the implementation of std::transform (on my platform)
    > and it goes something like:-
    >
    > template<class _InIt,
    > class _OutIt,
    > class _Fn1> inline
    > _OutIt transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)
    > { // transform [_First, _Last) with _Func
    > for (; _First != _Last; ++_First, ++_Dest)
    > *_Dest = _Func(*_First);
    > return (_Dest);
    > }
    >
    > It looks like the
    >
    > *_Dest = _Func (*_First)
    >
    > would mean that transform expects the output objects to already exist.
    > Is that right? I keep crashing at the assignment. Does std::transform
    > require sequence containers with pre-reserved sizes?


    Either that or you have to use an appropriate iterator adaptor. You
    could do a number of things:

    transform( input.begin(), input.end(), input.begin(), &doSomething );

    This assumes you won't need the input after the transform is done. If
    you do, then use an inserter...

    vector<wstring> output;
    transform( input.begin(), input.end(),
    back_inserter( output ), &doSomething );

    The back_insert_iterator converts assignment into a push_back. There is
    also a front_inserter and an inserter.

    http://www.sgi.com/tech/stl/back_insert_iterator.html
    http://www.sgi.com/tech/stl/front_insert_iterator.html
    and
    http://www.sgi.com/tech/stl/insert_iterator.html

    --
    There are two things that simply cannot be doubted, logic and perception.
    Doubt those, and you no longer have anyone to discuss your doubts with,
    nor any ability to discuss them.
     
    Daniel T., Oct 12, 2006
    #4
  5. Vijai Kalyan

    Old Wolf Guest

    Daniel T. wrote:
    > "Vijai Kalyan" <> wrote:
    > > std::set<std::wstring> input;
    > > std::set<std::wstring> output;
    > >
    > > std::transform (input.begin(), input.end(), output.begin(),
    > > doSomething);

    >
    > transform( input.begin(), input.end(), input.begin(), &doSomething );


    I don't think this is valid for a set -- the transformation might
    mess up the set's ordering (if it even lets you write to input.begin())
     
    Old Wolf, Oct 12, 2006
    #5
  6. Vijai Kalyan

    red floyd Guest

    Vijai Kalyan wrote:
    > Doh!
    >
    > The documentation says that the output range must be valid. THen the
    > question becomes:-
    >
    > I got a bunch of objects. I have to transform them in some way and
    > insert them into a destination. How would I do that?
    >
    > -vijai.


    std::back_inserter()
     
    red floyd, Oct 12, 2006
    #6
  7. Vijai Kalyan

    Daniel T. Guest

    "Old Wolf" <> wrote:
    > Daniel T. wrote:
    >> "Vijai Kalyan" <> wrote:
    >>
    >>> std::set<std::wstring> input;
    >>> std::set<std::wstring> output;
    >>>
    >>> std::transform (input.begin(), input.end(), output.begin(),
    >>> doSomething);

    >>
    >> transform( input.begin(), input.end(), input.begin(),
    >> &doSomething );

    >
    > I don't think this is valid for a set -- the transformation might
    > mess up the set's ordering (if it even lets you write to
    > input.begin())


    It wouldn't even compile if 'input' is a set.

    --
    There are two things that simply cannot be doubted, logic and perception.
    Doubt those, and you no longer have anyone to discuss your doubts with,
    nor any ability to discuss them.
     
    Daniel T., Oct 13, 2006
    #7
    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. Steven T. Hatton
    Replies:
    4
    Views:
    3,905
    Rob Williscroft
    Dec 5, 2004
  2. Peter Jansson
    Replies:
    5
    Views:
    6,313
    Ivan Vecerina
    Mar 17, 2005
  3. Wenjie

    if (f() != FAIL) or if (FAIL != f())?

    Wenjie, Jul 28, 2003, in forum: C Programming
    Replies:
    3
    Views:
    450
    E. Robert Tisdale
    Jul 31, 2003
  4. Tom Lynch
    Replies:
    2
    Views:
    2,037
    Tom Lynch
    Oct 12, 2007
  5. Ralf Goertz

    std::transform for std::map

    Ralf Goertz, Mar 16, 2009, in forum: C++
    Replies:
    6
    Views:
    2,780
    Ralf Goertz
    Mar 18, 2009
Loading...

Share This Page