vector<int> fillVector(int arguments ...)

A

Andreas Krueger

Hi!

I am fed up with
vector<int> iv;
iv.push_back(42); iv.push_back(9); iv.push_back(11); ...

and would rather use a function "fillVector":
vector<int> iv = fillVector(42,9,11);

like in Mathematica(tm): someList={42,9,11};
or even some2dimList={{42},{9,11}};

But there are some difficulties with it.
Perhaps you have good ideas how to solve it?
The sample code is below.
If you don't like templates, just leave out template<class T>
and replace every single "T" by "int"


a) In Visual C++ 6 the sample code works WITHOUT an ending 0:
25 vector<int> intvec=fillVector(800,500,200,300,400);
but in gcc 2.95.2 the last parameter HAS TO BE 0:
25 vector<int> intvec=fillVector(800,500,200,300,400,0);
otherwise the for(;;) breaks much later.

Moreover, even in Visual C++ 6, the problem occurs with
un-0-terminated lists when I use the vector result as
a parameter for some other function.
(see line 33) - so probably it's just by chance that it
works if I use an intermediate storage vector as in line 25

So: Is there any other way to notice the end (or length)
of a va_list ??? so that the list of parameters doesn't
need to be 0-terminated?


b) It works with "int" but not with "string"
because there doesn't seem to be a "0" in string - or is there?
compiler reports problem in line 15 because of (p==0)
even ( p == (T) 0 ) or a ( p == T(0) ) doesn't help.

any ideas concerning the "0" in string?


c) Any ideas for 2(3)dimensional arrays?
vector<vector<int> > intMatrix=fillVector((800,500),(200,300),(400,12));


Please answer not only to the list but also to my email...

Many thanks in advance!
Andreas


sample code:


1 #include <vector>
2 #include <algorithm>
3 #include <iostream>
4 using namespace std;
5 #pragma warning(disable:4786)
6
7 #include <cstdarg>
8 template<class T> vector<T> fillVector(T noZeroes ...){
9 vector<T> theVector;
10 theVector.push_back(noZeroes);
11 va_list ap;
12 va_start(ap, noZeroes);
13 for (;;){
14 T p = va_arg(ap, T);
15 if (p==0 ) break;
16 theVector.push_back(p);
17 }
18 va_end(ap);
19 return theVector;
20 } // idea from chapter 7.6 of Stroustrup, 3rd Edition
21
22 void print_tab(int i) { cout<<i<<"\t"; };
23 void someFunction(vector<int> v){
for_each(v.begin(),v.end(),print_tab);
};
24
25 int main (){
26 vector<int> intvec=fillVector(800,500,200,300,400,0);
27 for_each(intvec.begin(),intvec.end(),print_tab);
28 cout<<"\n";
29
30 // vector<string> stringvec
=fillVector<string > ("Andreas","Test","Schubbidu","");
31 // for_each(stringvec.begin(),stringvec.end(),print_tab);
32
33 someFunction(fillVector(800,500,200,300,400));
34 return 0;
35 }
 
R

Rob Williscroft

Andreas Krueger wrote in @posting.google.com:
I am fed up with
vector<int> iv;
iv.push_back(42); iv.push_back(9); iv.push_back(11); ...

Note the solution I've snipped uses va_args as such it could
*never* portably work with non-POD types (i.e. std::string).

See defenition of append_container<>() below for an alternative
approach.

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

int data[3] = { 42, 9, 11 };

void test1()
{
std::vector< int > iv;
std::copy(
data,
data + (sizeof(data)/sizeof(data[0])),
std::back_inserter( iv )
);

std::copy(
iv.begin(),
iv.end(),
std::eek:stream_iterator< int >( std::cout, ", " )
);

std::cout << std::endl;
}



/* gcc 3.2 was happy with typename C::value_type but it
broke vc7.1 and bcc
*/
template < typename C, typename T, std::size_t N >
void append_container( C &c, T (&data)[ N ] )
{
std::copy( data, data + N, std::back_inserter( c ) );
}



void test2()
{
std::vector< int > iv;
append_container( iv, data );

std::copy(
iv.begin(),
iv.end(),
std::eek:stream_iterator< int >( std::cout, ", " )
);

std::cout << std::endl;
}


int main()
{
test1();
test2();
}

This works with msvc 7.1, gcc 3.2, and bcc 5.4 good look
with vc 6.0 though.

Rob.
 
P

Pete Becker

Rob said:
int data[3] = { 42, 9, 11 };

void test1()
{
std::vector< int > iv;
std::copy(
data,
data + (sizeof(data)/sizeof(data[0])),
std::back_inserter( iv )
);

Too much work. vector has a ctor and member functions that take ranges:

std::vector<int> iv(data, data + sizeof(data)/sizeof(data[0]));
iv.assign(data, data + sizeof(data)/sizeof(data[0]));
iv.insert(iv.end(), data, data + sizeof(data)/sizeof(data[0]));
 
J

Jerry Coffin

Hi!

I am fed up with
vector<int> iv;
iv.push_back(42); iv.push_back(9); iv.push_back(11); ...

and would rather use a function "fillVector":
vector<int> iv = fillVector(42,9,11);

Here's one (perhaps somewhat warped) way of getting something pretty
close:

#include <vector>

template<class T>
class fill_vector {
std::vector<T> data;
public:
fill_vector(T const &val) {
data.push_back(val);
}

fill_vector<T> &operator,(T const &t) {
data.push_back(t);
return *this;
}

operator std::vector<T>() { return data; }
};

template<class T>
fill_vector<T> fillVector(T const &t) {
return fill_vector<T>(t);
}

With this, you can do something like this:

std::vector<int> iv = (fillVector(42), 9, 11);

or:

std::vector<int> iv = (fillVector(42), 9, 11, 17, 21, 34, 99, 22);

or whatever -- you parenthesize the whole list, but call fillVector only
on the first element. After that, the magic of operator overloading
allows it to work with a list of arbitrary length. Note that this uses
the type of the operand to fillVector as the type of the vector that's
created, so if you wanted something like:

std::vector<double> dv = (fillVector(42), 11.0, 2, 17);

it won't work -- but for that situation, you could use:

std::vector<double> dv = (fill_vector<double>(42), 11.0, 2.2, 17);


and the usual arithmetic conversions would force all the numbers to
double.

Overloading the comma operator is generally viewed somewhat dimly
because it doesn't give a sequence point between evaluating the operands
like the built-in comma operator does. IMO, that causes no problem in
this case, because we expect list separator semantics rather than comma
operator semantics.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top