C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

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

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++)
View previous topic :: View next topic  
Author Message
Andreas Krueger
Guest





PostPosted: Sat Oct 18, 2003 12:57 pm    Post subject: vector<int> fillVector(int arguments ...) Reply with quote



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(;Wink 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 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 (;Wink{
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< 23 void someFunction(vector 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 =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 }
Back to top
Rob Williscroft
Guest





PostPosted: Sat Oct 18, 2003 1:36 pm    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote



Andreas Krueger wrote in news:59499c44.0310180457.3d188c39
@posting.google.com:

Quote:
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::ostream_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::ostream_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.
--
http://www.victim-prime.dsl.pipex.com/

Back to top
Pete Becker
Guest





PostPosted: Sat Oct 18, 2003 1:55 pm    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote



Rob Williscroft wrote:
Quote:


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]));

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

Back to top
Andreas Krueger
Guest





PostPosted: Mon Oct 20, 2003 7:32 pm    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote

Hi!
I herewith suggest/demand a better variableLengthType "..."
for the next version of C++.

Thanks to M.Lehn, B.v.Ingen-Schenau and J.Sebastian for all
the suggestions for variable length parameter-functions
vector<T> foo(T data ...).
Some problems remain, though.

I summarize 4 possible solutions
(none of which are really elegant
cause there's NO way of knowing va-length):
a) specialized vector-/matrix-type with overloaded comma-operator
DoubleDenseVector b(3);
b = 1, 2, 3; ([url]http://sourceforge.net/projects/flens/)[/url])
b) first argument (or template argument)
contains length of data
c) using a C-style array as an intermediate container, e.g.:
int tmparr[] = { 42, 9, 11 };
vector<int> iv(tmparr, tmparr + sizeof tmparr / sizeof *tmparr);
d) a sentinel brackets the data.

I like solution (d) but there are still problems with VA_ARG
and STRING (access violation crash) 'cause "va_arg" stems from
C (not C++) as I was told.

So herewith I suggest a better variableLengthType "..."
for the next version of C++.


remaining problems with va_arg:

1)
One seems to need a template specialisation for each C++ type
like string. See code below at // (*)
Here the (const) string data has to be read-in by va_arg as char*
and then (implicitly) converted to string:
parameter = va_arg(ap, char*); // (*)

unfortunately a more compact version like
if (typeid(T)==typeid(string)) parameter = va_arg(ap, char*);
else parameter = va_arg(ap, T);
doesn't compile as soon as one uses fillVector<int>

1a) Why? Other ideas?

1b) Is complete specialisation the only way of solving the string problem?


2)
Why does one need a int- and string-specialisation for
template<class T> void print_tab(T i){ cout< if one wants to use
template for_each(v.begin(),v.end(),print_tab<T>); };
??


thanks a lot.
Andreas



#pragma warning(disable:4786)
#include <vector>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
#include <cstdarg>

template<class T>
vector<T> fillVector(T sentinelDataSentinel ...){
T parameter, sentinel=sentinelDataSentinel;
vector<T> theVector;
va_list ap; va_start(ap, sentinelDataSentinel);
for (;Wink{
parameter = va_arg(ap, T);
if ( parameter == sentinel ) break;
theVector.push_back(parameter);
}
va_end(ap);
return theVector;
};

template<>
vector<string> fillVector<string>(string sentinelDataSentinel ...){
string parameter, sentinel=sentinelDataSentinel;
vector<string> theVector;
va_list ap; va_start(ap, sentinelDataSentinel);
for (;Wink{
parameter = va_arg(ap, char*); // (*)
if ( parameter == sentinel ) break;
theVector.push_back(parameter);
}
va_end(ap);
return theVector;
};

template<class T> void print_tab(T i){ cout< template<> void print_tab<string>(string i){ cout< template<> void print_tab<int> (int i) { cout<
template for_each(v.begin(),v.end(),print_tab<T>);
};

int main (){
vector<int> intvec=fillVector<int>(0,800,500,200,300,400,0);
coutVector<int>(intvec);
cout<<"n";
vector =fillVector<string>("stop","Andreas","Test","Schubbidu","stop");
coutVector<string>(stringvec);
return 0;
}





(Andreas Krueger) wrote in message news:<59499c44.0310180458.655b67da (AT) posting (DOT) google.com>...
Quote:
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.

[... see original message 18.10.2003]

Back to top
Andreas Müller
Guest





PostPosted: Tue Oct 21, 2003 7:30 am    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote

Andreas Krueger wrote:

Quote:
Hi!
I herewith suggest/demand a better variableLengthType "..."
for the next version of C++.

Thanks to M.Lehn, B.v.Ingen-Schenau and J.Sebastian for all
the suggestions for variable length parameter-functions
vector<T> foo(T data ...).
Some problems remain, though.

I summarize 4 possible solutions
(none of which are really elegant
cause there's NO way of knowing va-length):
a) specialized vector-/matrix-type with overloaded comma-operator
DoubleDenseVector b(3);

I didn't dig to deep into the thread, but I think that the solution
described this article is doing what you want:
http://www.moderncppdesign.com/publications/inline_containers.html

[snip]

--
To mail me directly, remove the NO*SPAM parts in
NO*SPAMxmen40 (AT) gmx (DOT) netNO*SPAM

Back to top
Andreas Krueger
Guest





PostPosted: Tue Oct 21, 2003 4:10 pm    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote

Quote:
From: Bjarne Stroustrup [mailto:bs (AT) research (DOT) att.com]
Sent: Tuesday, October 21, 2003 4:44 PM
Subject: Re: vector<int> fillVector(int arguments ...)

Ack.

I think that what you'll get in the next standard is something slightly
different: a notion of a sequence constructor
X(Elem*, Elem*)
that will be used to accept { ... } lists of Elements. That way, we can get

vector<int> v = { 1,2,3,4 };

just as we have

int a[] = { 1,2,3,4 };



Betrifft:Re: vector<int> fillVector(int arguments ...)
Datum:2003-10-20 12:32:54 PST
I herewith suggest/demand a better variableLengthType "..."
for the next version of C++.

[...snip...]

Quote:
- Bjarne
Bjarne Stroustrup, http://www.research.att.com/~bs






[email]usenet (AT) AndreasKrueger (DOT) de[/email] (Andreas Krueger) wrote in message news:<59499c44.0310201132.1cb01993 (AT) posting (DOT) google.com>...

Quote:
I herewith suggest/demand a better variableLengthType "..."
for the next version of C++.

[... snip ....]

see:
http://groups.google.com/groups?selm=59499c44.0310201132.1cb01993%40posting.google.com

Back to top
red floyd
Guest





PostPosted: Tue Oct 21, 2003 9:01 pm    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote

Andreas Krueger wrote:

Quote:
Hi!
I herewith suggest/demand a better variableLengthType "..."
for the next version of C++.

Thanks to M.Lehn, B.v.Ingen-Schenau and J.Sebastian for all
the suggestions for variable length parameter-functions
vector<T> foo(T data ...).
Some problems remain, though.

I summarize 4 possible solutions
(none of which are really elegant
cause there's NO way of knowing va-length):
a) specialized vector-/matrix-type with overloaded comma-operator
DoubleDenseVector b(3);
b = 1, 2, 3; ([url]http://sourceforge.net/projects/flens/)[/url])
b) first argument (or template argument)
contains length of data
c) using a C-style array as an intermediate container, e.g.:
int tmparr[] = { 42, 9, 11 };
vector<int> iv(tmparr, tmparr + sizeof tmparr / sizeof *tmparr);
d) a sentinel brackets the data.

I like solution (d) but there are still problems with VA_ARG
and STRING (access violation crash) 'cause "va_arg" stems from
C (not C++) as I was told.

So herewith I suggest a better variableLengthType "..."
for the next version of C++.


remaining problems with va_arg:

1)
One seems to need a template specialisation for each C++ type
like string. See code below at // (*)
Here the (const) string data has to be read-in by va_arg as char*
and then (implicitly) converted to string:
parameter = va_arg(ap, char*); // (*)

unfortunately a more compact version like
if (typeid(T)==typeid(string)) parameter = va_arg(ap, char*);
else parameter = va_arg(ap, T);
doesn't compile as soon as one uses fillVector<int

1a) Why? Other ideas?

1b) Is complete specialisation the only way of solving the string problem?


2)
Why does one need a int- and string-specialisation for
template if one wants to use
template for_each(v.begin(),v.end(),print_tab<T>); };
??


thanks a lot.
Andreas

[redacted]


How about:


double d[] = { 1.0, 2.0, 3.0 };
std::vector<double> v(d,d+3);


Back to top
red floyd
Guest





PostPosted: Tue Oct 21, 2003 9:39 pm    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote

red floyd wrote:
Quote:
Andreas Krueger wrote:

[redacted]
c) using a C-style array as an intermediate container, e.g.:
int tmparr[] = { 42, 9, 11 }; vector<int> iv(tmparr,
tmparr + sizeof tmparr / sizeof *tmparr);

[redacted]

How about:


double d[] = { 1.0, 2.0, 3.0 };
std::vector<double> v(d,d+3);
3
Whoops! Never mind. Missed the OP's item c).



Back to top
Martijn Lievaart
Guest





PostPosted: Wed Oct 22, 2003 12:31 pm    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote

On Mon, 20 Oct 2003 12:32:53 -0700, Andreas Krueger wrote:

Quote:
Hi!
I herewith suggest/demand a better variableLengthType "..."
for the next version of C++.

How about this (mind you, this hasn't been near a compiler, and probably
is not very efficient, depending on the implementation of
VectorFillerHelpers constructor):

// A real implementation would have up to say 50 parameters.
// A lot of work, but only has to be done once.
// (Hint, write a program to generate this!)

class Sentinel {};

template<class T, class T2, class T3>
class VectorFillerHelper
{
protected:
vector<T> vec;
public:
VectorFillerHelper(T t, T2 t2, T3 t3);
};

template<class T, class T2>
class VectorFillerHelper<T, T2, Sentinel>
{
protected:
vector<T> vec;
public:
VectorFillerHelper(T t, T2 t2);
};

template<class T>
class VectorFillerHelper<T, Sentinel, Sentinel>
{
protected:
vector<T> vec;
public:
VectorFillerHelper(T t);
};

template<class T, class T2=Sentinel, class T3=Sentinel>
class VectorFiller : public VectorFillerHelper<T, T2, T3>
{
public:
operator vector<T>() { return vec; }
VectorFiller(T t, T2 t2, T3 t3) : VectorFillerHelper(t, t2, t3) {}
VectorFiller(T t, T2 t2) : VectorFillerHelper(t, t2) {}
VectorFiller(T t) : VectorFillerHelper(t) {}
};

Note that the frist type passed, must be the type of the vector, e.g.

vector<string> v(VectorFiller(string("1"), "2", "3"));

This can be avoided like this:

replace:
VectorFiller(T t, T2 t2) : VectorFillerHelper(t, t2) {}
with:
template<class U, U2>
VectorFiller(U t, U2 t2) : VectorFillerHelper(t, t2) {}

Also note that using non PAD types quickly runs into undefined behaviour
with varargs, best to avoid varargs completely.

Another aproach could be to have a generic filler, where the type of the
container is passed as the first template parameter. I'm not completely
sure how feasable this is, but I think it can be done.

HTH,
M4

Back to top
Jerry Coffin
Guest





PostPosted: Thu Oct 23, 2003 7:16 pm    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote

In article <59499c44.0310180457.3d188c39 (AT) posting (DOT) google.com>,
[email]usenet (AT) AndreasKrueger (DOT) de[/email] says...
Quote:
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.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Back to top
Andreas Krueger
Guest





PostPosted: Mon Nov 10, 2003 2:33 pm    Post subject: Re: vector<int> fillVector(int arguments ...) Reply with quote

thought it might be necessary to mention this,
.... just for the protocol.

;-) Andreas


Quote:
-----Original Message-----
From: Bjarne Stroustrup [mailto:bs (AT) research (DOT) att.com]
Sent: Tuesday, October 21, 2003 7:47 PM

Please be sure to mention that for now that's just a
proposal; not a voted-in feature.

[...snip...]

- Bjarne
Bjarne Stroustrup, http://www.research.att.com/~bs


(Andreas Krueger) wrote in message news:<59499c44.0310210810.76bb955a (AT) posting (DOT) google.com>...

Quote:
From: Bjarne Stroustrup [mailto:bs (AT) research (DOT) att.com]

Ack.

I think that what you'll get in the next standard
is something slightly different:
a notion of a sequence constructor
X(Elem*, Elem*)
that will be used to accept { ... } lists of Elements.
That way, we can get
vector<int> v = { 1,2,3,4 };

just as we have

int a[] = { 1,2,3,4 };

[...snip...]

- Bjarne
Bjarne Stroustrup, http://www.research.att.com/~bs

Back to top
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++) All times are GMT
Page 1 of 1

 
 


Powered by phpBB © 2001, 2006 phpBB Group