Vector reserve in a for_each

Discussion in 'C++' started by Chris Roth, Feb 24, 2007.

  1. Chris Roth

    Chris Roth Guest

    I have a vector of vectors:
    vector< vector<double> > v;
    and have initialized it with:
    v( 5 );
    as I know I will have 5 columns of data. At this point, I read text file
    data into each of the the vectors using push_back. I know that I will be
    reading in 5000 elements into each vector, so I use reserve:
    ifstream f( "file.txt" );
    if(f.is_open())
    {
    for( vector< vector<double> >::iterator itr = v.begin();
    itr != v.end(); ++itr )
    {
    itr->reserve(5000);
    }
    double d;
    while(f >> d)
    {
    m_data[0].push_back( d );
    f >> d;
    m_data[1].push_back( d );
    f >> d;
    m_data[2].push_back( d );
    f >> d;
    m_data[3].push_back( d );
    f >> d;
    m_data[4].push_back( d );
    }
    }
    However, could I use a for_each to set the reserve of the vectors? Or is
    there a different/better way to read in the 5 column text data?

    Thanks in advance.
    Chris Roth, Feb 24, 2007
    #1
    1. Advertising

  2. * Chris Roth:
    > I have a vector of vectors:
    > vector< vector<double> > v;
    > and have initialized it with:
    > v( 5 );
    > as I know I will have 5 columns of data. At this point, I read text file
    > data into each of the the vectors using push_back. I know that I will be
    > reading in 5000 elements into each vector, so I use reserve:
    > ifstream f( "file.txt" );
    > if(f.is_open())
    > {
    > for( vector< vector<double> >::iterator itr = v.begin();
    > itr != v.end(); ++itr )
    > {
    > itr->reserve(5000);
    > }
    > double d;
    > while(f >> d)
    > {
    > m_data[0].push_back( d );
    > f >> d;
    > m_data[1].push_back( d );
    > f >> d;
    > m_data[2].push_back( d );
    > f >> d;
    > m_data[3].push_back( d );
    > f >> d;
    > m_data[4].push_back( d );
    > }
    > }
    > However, could I use a for_each to set the reserve of the vectors?


    You could, but a loop is much cleaner.

    However, I'd use an indexing loop, not an iterator-based loop.

    Like

    for( size_t i = 0; i < v.size(); ++i ) { v.at(i).reserve( 5000 ); }


    > Or is
    > there a different/better way to read in the 5 column text data?


    Sure: define "better".

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Feb 24, 2007
    #2
    1. Advertising

  3. >
    > You could, but a loop is much cleaner.
    >
    > However, I'd use an indexing loop, not an iterator-based loop.
    >
    > Like
    >
    > for( size_t i = 0; i < v.size(); ++i ) { v.at(i).reserve( 5000 ); }
    >


    A voice of sanity, some people go completely overboard on writing
    generic loops. Although I'd use [] not at for this very simple case.

    john
    John Harrison, Feb 24, 2007
    #3
  4. John Harrison, Feb 24, 2007
    #4
  5. Chris Roth

    Alan Johnson Guest

    Chris Roth wrote:
    > I have a vector of vectors:
    > vector< vector<double> > v;
    > and have initialized it with:
    > v( 5 );
    > as I know I will have 5 columns of data. At this point, I read text file
    > data into each of the the vectors using push_back. I know that I will be
    > reading in 5000 elements into each vector, so I use reserve:
    > ifstream f( "file.txt" );
    > if(f.is_open())
    > {
    > for( vector< vector<double> >::iterator itr = v.begin();
    > itr != v.end(); ++itr )
    > {
    > itr->reserve(5000);
    > }
    > double d;
    > while(f >> d)
    > {
    > m_data[0].push_back( d );
    > f >> d;
    > m_data[1].push_back( d );
    > f >> d;
    > m_data[2].push_back( d );
    > f >> d;
    > m_data[3].push_back( d );
    > f >> d;
    > m_data[4].push_back( d );
    > }
    > }
    > However, could I use a for_each to set the reserve of the vectors? Or is
    > there a different/better way to read in the 5 column text data?
    >
    > Thanks in advance.


    Here's how you'd do it. But I would comment that in the amount of time
    it took me to get the syntax just right I could have written the
    equivalent for loop a hundred times over.

    #include <vector>
    #include <functional>
    #include <algorithm>

    int main()
    {
    std::vector< std::vector<double> > v(5) ;

    std::for_each(v.begin(), v.end(),
    std::bind2nd(std::mem_fun_ref(&std::vector<double>::reserve),
    5000)) ;
    }

    --
    Alan Johnson
    Alan Johnson, Feb 24, 2007
    #5
  6. Chris Roth

    Alan Johnson Guest

    John Harrison wrote:
    >
    >> A voice of sanity, some people go completely overboard on writing
    >> generic loops.

    >
    > http://www.regdeveloper.co.uk/2006/08/08/cplusplus_loops/


    Best quote from that article:

    "Don't be silly, it's an int! The day they change the language name to
    ++C, that's the day I'll start taking pre-incrementing seriously."

    From now on I will be referring to C++ and ++C. :)

    --
    Alan Johnson
    Alan Johnson, Feb 24, 2007
    #6
  7. Chris Roth

    kwikius Guest

    On 24 Feb, 08:42, Alan Johnson <> wrote:
    > Chris Roth wrote:
    > > I have a vector of vectors:
    > > vector< vector<double> > v;
    > > and have initialized it with:
    > > v( 5 );
    > > as I know I will have 5 columns of data. At this point, I read text file
    > > data into each of the the vectors using push_back. I know that I will be
    > > reading in 5000 elements into each vector, so I use reserve:
    > > ifstream f( "file.txt" );
    > > if(f.is_open())
    > > {
    > > for( vector< vector<double> >::iterator itr = v.begin();
    > > itr != v.end(); ++itr )
    > > {
    > > itr->reserve(5000);
    > > }
    > > double d;
    > > while(f >> d)
    > > {
    > > m_data[0].push_back( d );
    > > f >> d;
    > > m_data[1].push_back( d );
    > > f >> d;
    > > m_data[2].push_back( d );
    > > f >> d;
    > > m_data[3].push_back( d );
    > > f >> d;
    > > m_data[4].push_back( d );
    > > }
    > > }
    > > However, could I use a for_each to set the reserve of the vectors? Or is
    > > there a different/better way to read in the 5 column text data?

    >
    > > Thanks in advance.

    >
    > Here's how you'd do it. But I would comment that in the amount of time
    > it took me to get the syntax just right I could have written the
    > equivalent for loop a hundred times over.


    Somehow I just feel that things could be so much sweeter...

    #include <algorithm>
    #include <functional>
    #include <vector>
    #include <iostream>
    #include <boost/preprocessor/cat.hpp>

    #define CONTAINER_FUN_ADAPT1(ret,fun,arg) \
    namespace impl{\
    struct BOOST_PP_CAT(fun,_fun){\
    arg v;\
    BOOST_PP_CAT(fun,_fun)(arg v_in)\
    : v(v_in){}\
    template <typename C>\
    ret operator()( C & c)const\
    {\
    c. fun(v);\
    }\
    };\
    }\
    impl::BOOST_PP_CAT(fun,_fun) fun( arg v)\
    {\
    return impl::BOOST_PP_CAT(fun,_fun)(v);\
    }\





    namespace my{

    // reserve space in a container adaptor
    CONTAINER_FUN_ADAPT1(void,reserve,size_t);

    // wrap ugly std:: syntax
    template <typename Seq, typename F>
    void for_each(Seq & seq,F const & f)
    {
    std::for_each(seq.begin(),seq.end(),f);
    }
    }

    int main()
    {
    //--------ugly --------------

    std::vector< std::vector<double> > v1(5) ;

    std::for_each(
    v1.begin(), v1.end(),
    std::bind2nd(
    std::mem_fun_ref(
    &std::vector<double>::reserve
    ),
    5000
    )
    );
    //check it worked...
    std::cout << (int) v1[2].capacity() <<'\n';

    //----- pretty ---------------

    std::vector< std::vector<double> > v2(5) ;

    my::for_each(v2,my::reserve(5000));

    //check it worked...
    std::cout << (int) v2[2].capacity() <<'\n';

    }
    kwikius, Feb 24, 2007
    #7
  8. Chris Roth

    Alan Johnson Guest

    kwikius wrote:
    > On 24 Feb, 08:42, Alan Johnson <> wrote:
    >> Chris Roth wrote:
    >>> I have a vector of vectors:
    >>> vector< vector<double> > v;
    >>> and have initialized it with:
    >>> v( 5 );
    >>> as I know I will have 5 columns of data. At this point, I read text file
    >>> data into each of the the vectors using push_back. I know that I will be
    >>> reading in 5000 elements into each vector, so I use reserve:
    >>> ifstream f( "file.txt" );
    >>> if(f.is_open())
    >>> {
    >>> for( vector< vector<double> >::iterator itr = v.begin();
    >>> itr != v.end(); ++itr )
    >>> {
    >>> itr->reserve(5000);
    >>> }
    >>> double d;
    >>> while(f >> d)
    >>> {
    >>> m_data[0].push_back( d );
    >>> f >> d;
    >>> m_data[1].push_back( d );
    >>> f >> d;
    >>> m_data[2].push_back( d );
    >>> f >> d;
    >>> m_data[3].push_back( d );
    >>> f >> d;
    >>> m_data[4].push_back( d );
    >>> }
    >>> }
    >>> However, could I use a for_each to set the reserve of the vectors? Or is
    >>> there a different/better way to read in the 5 column text data?
    >>> Thanks in advance.

    >> Here's how you'd do it. But I would comment that in the amount of time
    >> it took me to get the syntax just right I could have written the
    >> equivalent for loop a hundred times over.

    >
    > Somehow I just feel that things could be so much sweeter...
    >
    > #include <algorithm>
    > #include <functional>
    > #include <vector>
    > #include <iostream>
    > #include <boost/preprocessor/cat.hpp>
    >
    > #define CONTAINER_FUN_ADAPT1(ret,fun,arg) \
    > namespace impl{\
    > struct BOOST_PP_CAT(fun,_fun){\
    > arg v;\
    > BOOST_PP_CAT(fun,_fun)(arg v_in)\
    > : v(v_in){}\
    > template <typename C>\
    > ret operator()( C & c)const\
    > {\
    > c. fun(v);\
    > }\
    > };\
    > }\
    > impl::BOOST_PP_CAT(fun,_fun) fun( arg v)\
    > {\
    > return impl::BOOST_PP_CAT(fun,_fun)(v);\
    > }\
    >
    >
    >
    >
    >
    > namespace my{
    >
    > // reserve space in a container adaptor
    > CONTAINER_FUN_ADAPT1(void,reserve,size_t);
    >
    > // wrap ugly std:: syntax
    > template <typename Seq, typename F>
    > void for_each(Seq & seq,F const & f)
    > {
    > std::for_each(seq.begin(),seq.end(),f);
    > }
    > }
    >
    > int main()
    > {
    > //--------ugly --------------
    >
    > std::vector< std::vector<double> > v1(5) ;
    >
    > std::for_each(
    > v1.begin(), v1.end(),
    > std::bind2nd(
    > std::mem_fun_ref(
    > &std::vector<double>::reserve
    > ),
    > 5000
    > )
    > );
    > //check it worked...
    > std::cout << (int) v1[2].capacity() <<'\n';
    >
    > //----- pretty ---------------
    >
    > std::vector< std::vector<double> > v2(5) ;
    >
    > my::for_each(v2,my::reserve(5000));
    >
    > //check it worked...
    > std::cout << (int) v2[2].capacity() <<'\n';
    >
    > }
    >
    >
    >
    >


    This thread is a good example of why C++ needs lambda functions (or
    anonymous functions, or function literals, or whatever you want to call
    them). The concept of doing the same thing to every item in a container
    is arguably the most common algorithm one would apply to a container,
    but use C++'s for_each is just such a pain.

    Either you need to write a functor, which typically needs to be a full
    blown class with at least operator() and a constructor that wraps up
    enough of the local state to be useful, or you have to play around with
    binders and generic function objects. boost::function and boost::bind
    seem like the answer for the few moments until you actually try to do
    something non-trivial with them, like compose two functions that are
    created by binding parameters on two other functions, at which point you
    realize that because this is all just a library hack, you have to
    surround the inner binds with a boost::protect. And lord help you if
    you are trying to do any of this in a scope where it isn't convenient to
    add a "using namespace boost ;".

    Typically after struggling with indecipherable compiler errors for an
    hour or so, most people just give up and spend 2 minutes writing a for loop.

    --
    Alan Johnson
    Alan Johnson, Feb 25, 2007
    #8
  9. Chris Roth

    kwikius Guest

    On 25 Feb, 00:58, Alan Johnson <> wrote:
    > kwikius wrote:


    <...>

    > This thread is a good example of why C++ needs lambda functions (or
    > anonymous functions, or function literals, or whatever you want to call
    > them). The concept of doing the same thing to every item in a container
    > is arguably the most common algorithm one would apply to a container,
    > but use C++'s for_each is just such a pain.


    One problem with a lot of standard library algorithms is the emphasis
    on iterators. Its annoying with for_each but starts to become
    ridiculous in functions action on two containers of which there are a
    lot. In many cases it seems to me that it would be trivial to hide
    iterators in the implementation, and use a e.g boost::range where only
    some part needs to be accessed( which IMO isnt as common as moving
    through the whole sequence). A function with 3 arguments is much more
    manageable to use and read and comprehend than one with 5. Note also
    that typos in argument such as providing an InputIterator2 instead of
    InputIterator1 would be eliminated, which currently won't necessarily
    be caught even at runtime currently.

    > Either you need to write a functor, which typically needs to be a full
    > blown class with at least operator() and a constructor that wraps up
    > enough of the local state to be useful, or you have to play around with
    > binders and generic function objects. boost::function and boost::bind
    > seem like the answer for the few moments until you actually try to do
    > something non-trivial with them, like compose two functions that are
    > created by binding parameters on two other functions, at which point you
    > realize that because this is all just a library hack, you have to
    > surround the inner binds with a boost::protect. And lord help you if
    > you are trying to do any of this in a scope where it isn't convenient to
    > add a "using namespace boost ;".
    >
    > Typically after struggling with indecipherable compiler errors for an
    > hour or so, most people just give up and spend 2 minutes writing a for loop.


    Yes, but... Personally I find the case for anonymous stateful
    functions in C++ not entirely convincing from what I have seen so far.

    Firstly by nature an anonymous function is not reusable. That means
    each expression using it needs testing and in all probability exactly
    the same expression will be reimplemented over and over. The use of
    named functions at namespace scope is by nature reusable and can be
    transferred into a header in a nice modular fashion. So for example
    the reserve function in my last post has now been added to my code
    base. It will probably never be used but nevertheless it sits in a
    header on my hard disc doing no harm. If it does get used for anything
    serious then it will need some tests but again once done the thing is
    modular and doesnt need to be repeated.

    The second problem is that anonymous functoids or whatever they are
    called make code look a mess. Everything is inline in the expresion.
    The only examples I have seen in C++ are pretty trivial but you can
    see the true nature of the junk produced when used seriously, by
    looking at some source code in a FP language such as OCaml. The nested
    inlining of functions within expressions makes code horrible to read
    and probably horrible to maintain.

    Also from what I have sen it looks like implementing them and sorting
    the design is extremely complicated. Is any benefit worth it?

    AFAICS the C++ powers that be seem to be concentrating on ever more
    complicated language features of which 'lambda' is one. The proponents
    of rival languages to C++ must be smirking into their sleeves at
    this. C++ is already probably the most difficult language to master,
    and once mastered it has a paltry out of date standard library. Even
    OCaml has a graphics library !. It seems obvious to me that the
    attraction of Java and C# is the "standard" libraries bundled rather
    than the language itself hence their success in recent years.

    Anyway FWIW here is some more code with the same simple trick of using
    overloaded functions to avoid the need for providing long winded
    template args to functors. I figured I should output the capacity of
    the vectors in the sequence to check the code. Again The (named)
    functions provide the interface and the functors the implementation.
    The quan::fun:: headers arent shown but its pretty trivial to
    replicate their functionality.

    And of course its all doable in the current language. Thank goodnees
    for the preprocessor ;-)


    regards
    Andy Little

    // headers from a useful little
    // (now quite extensive in fact)

    // library of homebrewed
    // functional bits and pieces.
    // (The quan::fun library is based on the boost::fusion
    // library but without the emphasis on iterators or MPL).

    #include <quan/fun/output.hpp>
    #include <quan/fun/for_each.hpp>

    // work from previous example added to the jumble...
    #include <quan/fun/container_reserve.hpp>
    // probably will never be used but
    // its doing no harm sitting on the hard disk
    // the CONTAINER_FUN_ADAPT1 macro is also reusable
    // so creating adaptors for other members functions
    // is trivial and the container_reserve header
    // provides docs on the syntax when I forget it :)


    #include <vector>
    #include <iostream>
    #include <boost/preprocessor/cat.hpp>

    // need a new adapter for vector.capacity
    // this can be reused same as the above
    // container_reserve header
    // Reuse! just copy pasted from the old macro
    // and chopped about a bit

    #define CONTAINER_FUN_ADAPT0(ret,fun) \
    namespace impl_detail{\
    struct BOOST_PP_CAT(fun,_fun){\
    template <typename C>\
    ret operator()( C & c)const\
    {\
    return c. fun();\
    }\
    };\
    }\
    impl_detail::BOOST_PP_CAT(fun,_fun) fun()\
    {\
    return impl_detail::BOOST_PP_CAT(fun,_fun)();\
    }

    namespace quan{ namespace fun{


    // get capacity of a container
    // using long long return supresses size_t
    // conversion warnings for output.
    // because the functor doesnt know about the container
    // except in it function op
    // its not possible to use the member::size_type
    #ifdef BOOST_HAS_LONG_LONG
    CONTAINER_FUN_ADAPT0(long long,capacity);
    #else
    CONTAINER_FUN_ADAPT0(size_t,capacity);
    #endif

    } }


    namespace quan{ namespace fun{namespace impl_detail{

    // implementation functor to output a function of its argument
    // to an ostream. (implemented here to output vect.capacity())
    // interface : quan::fun::eek:utput(stream, Fun, sep)
    // complements straight quan::fun::eek:utput(out, sep) function
    // which just outputs the value...

    template <typename Fun,typename CharType>
    struct output_fun{
    Fun const & fun;
    std::basic_ostream<CharType> & os;
    std::basic_string<CharType> sep;
    output_fun(
    std::basic_ostream<CharType> & os_in,
    Fun const & fun_in,
    std::basic_string<CharType> const & sep_in
    ):eek:s(os_in), fun(fun_in), sep(sep_in){}

    template <typename T>
    struct result{
    typedef std::basic_ostream<CharType> & type;
    };

    template <typename T>
    typename result<T>::type
    operator()(T const & t)const
    {
    return os << fun(t) << sep;
    }
    };
    }//impl_detail

    // interface functions
    // original quan::fun::eek:utput(stream, sep) function
    // is trivially overloaded to
    // return the different functor above
    template <typename Fun,typename CharType>
    inline
    impl_detail::eek:utput_fun<Fun,CharType>
    output(
    std::basic_ostream<CharType>& os,
    Fun const & fun,
    std::basic_string<CharType>const & sep
    )
    {
    return impl_detail::eek:utput_fun<Fun,CharType>(os,fun,sep);
    }
    // needs const char* overload as std::string<CharType>
    // cannot be deduced from CharType* in this context
    template <typename Fun,typename CharType>
    inline
    impl_detail::eek:utput_fun<Fun,CharType>
    output(
    std::basic_ostream<CharType>& os,
    Fun const & fun,
    const CharType* sep
    )
    {
    return output(os,fun,std::basic_string<CharType>(sep));
    }

    }}

    int main()
    {

    using quan::fun::for_each;
    using quan::fun::for_each_and_last;
    using quan::fun::capacity;
    using quan::fun::reserve;
    using quan::fun::eek:utput;

    std::vector< std::vector<double> > v2(5) ;

    for_each(v2,reserve(5000));

    // check it worked..

    // for_each_and_last...
    // like for each but uses second function on last element
    // used here to get a separator except for last element
    // which gives return character

    for_each_and_last(
    v2,
    output(std::cout,capacity() , " "),
    output(std::cout,capacity() , "\n")
    );
    }
    /*
    ??>test
    5000 5000 5000 5000 5000

    ??>
    */
    kwikius, Feb 25, 2007
    #9
  10. Chris Roth

    Rolf Magnus Guest

    Alan Johnson wrote:

    > John Harrison wrote:
    >>
    >>> A voice of sanity, some people go completely overboard on writing
    >>> generic loops.

    >>
    >> http://www.regdeveloper.co.uk/2006/08/08/cplusplus_loops/

    >
    > Best quote from that article:
    >
    > "Don't be silly, it's an int! The day they change the language name to
    > ++C, that's the day I'll start taking pre-incrementing seriously."
    >
    > From now on I will be referring to C++ and ++C. :)
    >


    My favorite is:

    "If the C++ overlords believe that the construction of nearly every loop
    should be a sort of inline Sudoku puzzle, surely the problem must be that
    we are simply too stupid to use the language?"
    Rolf Magnus, Mar 2, 2007
    #10
    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. john smith

    vector.reserve

    john smith, Jul 25, 2003, in forum: C++
    Replies:
    5
    Views:
    684
    John Harrison
    Jul 25, 2003
  2. Alex Vinokur

    vector : reserve(LONG_MAX)

    Alex Vinokur, Apr 22, 2004, in forum: C++
    Replies:
    2
    Views:
    445
    Pete Becker
    Apr 22, 2004
  3. Matthias Kaeppler

    seg-fault on vector-auto-reserve

    Matthias Kaeppler, Feb 27, 2005, in forum: C++
    Replies:
    2
    Views:
    460
    Victor Bazarov
    Feb 27, 2005
  4. Gary Kuehn
    Replies:
    2
    Views:
    450
    Gary Kuehn
    Jul 19, 2005
  5. Replies:
    8
    Views:
    1,896
    Csaba
    Feb 18, 2006
Loading...

Share This Page