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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language (comp.lang.c++) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.