Initializing vectors in one line

E

Emanuel Ziegler

Hi,

I am using the vector class from the STL. Normally, I initialize values
element by element, which is very uncomfortable and sometimes impossible
(e.g. when passing a constant vector to an inherited constructor, since I
cannot create a temporary vector before calling).

Is there a possibility to assign a vector in one line, like it is possible
for arrays?

I want to write code like this:

#include <vector>
typedef std::vector<int> ivec;
void test (ivec w) {};
int main () {
// Is there a possibility to make these lines valid
// (e.g. by extending the vector class)?
ivec v = {1, 2};
v = {3, 4};
test({5, 6});
return 0;
}

Is there at least a workaround for calling

aconstructor () : inheritedconstructor({5, 6}) {
...
}

where inheritedconstructor needs a vector?


Please help,
Emanuel
 
J

John Harrison

Emanuel Ziegler said:
Hi,

I am using the vector class from the STL. Normally, I initialize values
element by element, which is very uncomfortable and sometimes impossible
(e.g. when passing a constant vector to an inherited constructor, since I
cannot create a temporary vector before calling).

Is there a possibility to assign a vector in one line, like it is possible
for arrays?

I want to write code like this:

#include <vector>
typedef std::vector<int> ivec;
void test (ivec w) {};
int main () {
// Is there a possibility to make these lines valid
// (e.g. by extending the vector class)?
ivec v = {1, 2};
v = {3, 4};
test({5, 6});
return 0;
}

Is there at least a workaround for calling

aconstructor () : inheritedconstructor({5, 6}) {
...
}

where inheritedconstructor needs a vector?


Please help,
Emanuel

How about this? No need for a new type of vector.

#include <vector>
typedef std::vector<int> ivec;

const int one_two[] = { 1, 2 };
const int three_four[] = { 3, 4 };
const int five_six[] = { 5, 6 };

void test (ivec w) {};
int main () {
ivec v(one_two, one_two + 2);
v = ivec(three_four, three_four + 2);
test(ivec(five_six, five_six + 2));
return 0;
}

john
 
S

Sharad Kala

Emanuel Ziegler said:
Hi,

I am using the vector class from the STL. Normally, I initialize values
element by element, which is very uncomfortable and sometimes impossible
(e.g. when passing a constant vector to an inherited constructor, since I
cannot create a temporary vector before calling).

Is there a possibility to assign a vector in one line, like it is possible
for arrays?

I want to write code like this:

#include <vector>
typedef std::vector<int> ivec;
void test (ivec w) {};
int main () {
// Is there a possibility to make these lines valid
// (e.g. by extending the vector class)?
ivec v = {1, 2};
v = {3, 4};
test({5, 6});
return 0;
}

You should probably see all the vector constructors.
Here is a demo code -

#include <vector>
#include <iostream>
using namespace std;

int main(){
typedef vector<int> intVec;
intVec vec(10, 5);

intVec::const_iterator it;
for( it=vec.begin(); it!=vec.end(); it++)
cout << *it; // Print 5 ten times.

int arr[]={1, 2, 3, 4};
intVec vec2(arr, arr+4);
for( it=vec2.begin(); it!=vec2.end(); it++)
cout << *it; // Print 1234

}
 
E

Emanuel Ziegler

John said:
#include <vector>
typedef std::vector<int> ivec;

const int one_two[] = { 1, 2 };
const int three_four[] = { 3, 4 };
const int five_six[] = { 5, 6 };

void test (ivec w) {};
int main () {
ivec v(one_two, one_two + 2);
v = ivec(three_four, three_four + 2);
test(ivec(five_six, five_six + 2));
return 0;
}

This seems to be a practical solution, although I need to define the
constants first (not really a one-liner, but I can live with it).

Thanks,
Emanuel
 
J

John Carson

John Harrison said:
How about this? No need for a new type of vector.

#include <vector>
typedef std::vector<int> ivec;

const int one_two[] = { 1, 2 };
const int three_four[] = { 3, 4 };
const int five_six[] = { 5, 6 };

void test (ivec w) {};
int main () {
ivec v(one_two, one_two + 2);
v = ivec(three_four, three_four + 2);
test(ivec(five_six, five_six + 2));
return 0;
}

john

As an alternative to

v = ivec(three_four, three_four + 2);

you can also use:

v.assign(three_four, three_four + 2);
 
T

tom_usenet

Hi,

I am using the vector class from the STL. Normally, I initialize values
element by element, which is very uncomfortable and sometimes impossible
(e.g. when passing a constant vector to an inherited constructor, since I
cannot create a temporary vector before calling).

Is there a possibility to assign a vector in one line, like it is possible
for arrays?

There are many ways, but all require you to write or use some kind of
library. There have been various posts on this in the past (try google
groups), and there are a couple of free STL initialization libraries
around: http://www.cs.auc.dk/~nesotto/init/ and
http://www.bdsoft.com/tools/initutil.html

The former looks better to me, since it doesn't rely on string
parsing.

Tom
 
E

Emanuel Ziegler

tom_usenet said:
There are many ways, but all require you to write or use some kind of
library. There have been various posts on this in the past (try google
groups), and there are a couple of free STL initialization libraries
around: http://www.cs.auc.dk/~nesotto/init/ and
http://www.bdsoft.com/tools/initutil.html

The former looks better to me, since it doesn't rely on string
parsing.

Hmm, the first library has a very elegant implementation, but uses an
unusual syntax and does only allow initializations. The second library uses
a very intuitive syntax and can also be used as a parameter when calling
functions, but it uses strings.
Hard decision...

Thanks,
Emanuel
 
E

Emanuel Ziegler

tom_usenet said:
There are many ways, but all require you to write or use some kind of
library. There have been various posts on this in the past (try google
groups), and there are a couple of free STL initialization libraries
around: http://www.cs.auc.dk/~nesotto/init/ and
http://www.bdsoft.com/tools/initutil.html

By looking at the libraries above I had one very simple idea:

--- source begins here ---

#include <iostream>
#include <vector>

using namespace std;

template <class T, class A = allocator<T> >
class myvector : public vector<T,A> {
public:
// call inherited constructors
explicit myvector (const A &alloc = A())
: vector<T,A>(alloc)
{}
explicit myvector (size_type n,
const T& value = T(),
const A& alloc = A())
: vector<T,A>(n,value,alloc)
{}
template <class InputIterator>
myvector (InputIterator first,
InputIterator last,
const A &alloc = A())
: vector<T,A>(first,last,alloc)
{}
myvector (const vector<T,A> &x)
: vector<T,A>(x)
{}
using vector<T,A>::eek:perator=;
// providing new functionality
myvector & operator= (T newitem) {
clear();
push_back(newitem);
return *this;
}
myvector & operator+= (T newitem) {
push_back(newitem);
return *this;
}
myvector & operator, (T newitem) {
push_back(newitem);
return *this;
}
};

typedef myvector<int> ivec;

void printivec (ivec v) {
cout << v[0];
for ( int i = 1; i < v.size(); i++ )
cout << ", " << v;
cout << endl;
}

int main () {
myvector<int> v;
v = 1, 2, 3; // set vector
v += 4, 5, 6; // append items
printivec((ivec(0), 1, 2)); // 1, 2
printivec((ivec(v), 7, 8)); // 1, 2, 3, 4, 5, 6, 7, 8
printivec((v, 7, 8)); // be careful: this syntax changes v !
printivec(v); // 1, 2, 3, 4, 5, 6, 7, 8
}

--- source ends here ---

Is there a more elegant way to make all inherited constructors work in the
derived class?

The first two printivec calls may produce memory leaks on some compilers.


Thanks for the inspiration,
Emanuel
 
E

Emanuel Ziegler

typedef typename A::size_type size_type;

is missing in the declaration of myvector directly before public

Sorry,
Emanuel
 
J

Jonathan Turkanis

Emanuel Ziegler said:
Hi,

I am using the vector class from the STL. Normally, I initialize values
element by element, which is very uncomfortable and sometimes impossible
(e.g. when passing a constant vector to an inherited constructor, since I
cannot create a temporary vector before calling).

You might want to check out Thorsten Ottosen's Assign Library,
submitted to boost for review and featured in a recent CUJ article:

http://groups.yahoo.com/group/boost/files/assignment/

(To get access, you have to sign up for the boost developers list:
http://lists.boost.org/mailman/listinfo.cgi/boost)

Jonathan
 
L

Leor Zolman

tom_usenet said:
There are many ways, but all require you to write or use some kind of
library. There have been various posts on this in the past (try google
groups), and there are a couple of free STL initialization libraries
around: http://www.cs.auc.dk/~nesotto/init/ and
http://www.bdsoft.com/tools/initutil.html

By looking at the libraries above I had one very simple idea:

--- source begins here ---

#include <iostream>
#include <vector>

using namespace std;

template <class T, class A = allocator<T> >
class myvector : public vector<T,A> {
public:
// call inherited constructors
explicit myvector (const A &alloc = A())
: vector<T,A>(alloc)
{}
explicit myvector (size_type n,
const T& value = T(),
const A& alloc = A())
: vector<T,A>(n,value,alloc)
{}
template <class InputIterator>
myvector (InputIterator first,
InputIterator last,
const A &alloc = A())
: vector<T,A>(first,last,alloc)
{}
myvector (const vector<T,A> &x)
: vector<T,A>(x)
{}
using vector<T,A>::eek:perator=;
// providing new functionality
myvector & operator= (T newitem) {
clear();
push_back(newitem);
return *this;
}
myvector & operator+= (T newitem) {
push_back(newitem);
return *this;
}
myvector & operator, (T newitem) {
push_back(newitem);
return *this;
}
};

typedef myvector<int> ivec;

void printivec (ivec v) {
cout << v[0];
for ( int i = 1; i < v.size(); i++ )
cout << ", " << v;
cout << endl;
}

int main () {
myvector<int> v;
v = 1, 2, 3; // set vector
v += 4, 5, 6; // append items
printivec((ivec(0), 1, 2)); // 1, 2
printivec((ivec(v), 7, 8)); // 1, 2, 3, 4, 5, 6, 7, 8
printivec((v, 7, 8)); // be careful: this syntax changes v !
printivec(v); // 1, 2, 3, 4, 5, 6, 7, 8
}

--- source ends here ---

Is there a more elegant way to make all inherited constructors work in the
derived class?

The first two printivec calls may produce memory leaks on some compilers.


Thanks for the inspiration,
Emanuel


Nice, elegant idea. I got to wondering whether you can generalize it
further, making the container type a template parameter. There's probably a
better way than this, but here's a version that works for both vectors and
deques, at least:

//
// First stab at container-independent version...
//

#include <iostream>
#include <vector>
#include <list>
#include <deque>

using namespace std;

template <class C, class T, class A = allocator<T> >
class mycont : public C {
typedef typename A::size_type size_type;
public:
// call inherited constructors
explicit mycont (const A &alloc = A())
: C(alloc)
{}
explicit mycont (size_type n,
const T& value = T(),
const A& alloc = A())
: C(n,value,alloc)
{}
template <class InputIterator>
mycont (InputIterator first,
InputIterator last,
const A &alloc = A())
: C(first,last,alloc)
{}
mycont (const C &x)
: C(x)
{}
using C::eek:perator=;
// providing new functionality
mycont & operator= (T newitem) {
C::clear();
C::push_back(newitem);
return *this;
}
mycont & operator+= (T newitem) {
C::push_back(newitem);
return *this;
}
mycont & operator, (T newitem) {
C::push_back(newitem);
return *this;
}
};

typedef mycont<std::vector<int>,int> ivec;
typedef mycont<std::deque<double>,double> ddeq;


// templatized this ( for containers with subscripting, at least...)
// A ready-made equivalent for all containers is part of Scott Meyers'
// ESTLUtil.h, the latest version of which is included in the InitUtil v2
// distribution.

template<class T>
void printivec (const T &t) {
cout << t[0];
for ( int i = 1; i < t.size(); i++ )
cout << ", " << t;
cout << endl;
}

int main () {
ivec v;
v = 1, 2, 3; // set vector
v += 4, 5, 6; // append items
printivec((ivec(0), 1, 2)); // 1, 2
printivec((ivec(v), 7, 8)); // 1, 2, 3, 4, 5, 6, 7, 8
printivec((v, 7, 8)); // be careful: this syntax changes v !
printivec(v); // 1, 2, 3, 4, 5, 6, 7, 8

ddeq d; // deque of doubles
d = 1, 2.5, 3; // set deque
d += 4, 5, 6.6; // append items
printivec((ddeq(0), 1, 2)); // 1, 2
printivec((ddeq(d), 7, 8)); // 1, 2, 3, 4, 5, 6, 7, 8
printivec((d, 7, 8)); // be careful: this syntax changes v !
printivec(d); // 1, 2, 3, 4, 5, 6, 7, 8

return 0;
}


-leor


Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
T

Thorsten Ottosen

T

Thorsten Ottosen

Emanuel Ziegler said:
Is there a possibility to assign a vector in one line, like it is possible
for arrays?

Probably not if it should be optmially efficient. FYI the standard committee
is discussing
added such a facility to the langauage.

br

Thorsten
 
L

Leor Zolman

template <class C, class T, class A = allocator<T> >
class mycont : public C {
typedef typename A::size_type size_type;
public:

to:

template <class C, class A = allocator<typename C::value_type> >
class mycont : public C {
typedef typename A::size_type size_type;
typedef typename C::value_type T;
public:

so that later these:
typedef mycont<std::vector<int>,int> ivec;
typedef mycont<std::deque<double>,double> ddeq;
can be written as just:

typedef mycont<std::vector<int> > ivec;
typedef mycont<std::deque<double> > ddeq;


-leor


Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
E

Emanuel Ziegler

Leor said:
Nice, elegant idea.
Thanks.

I got to wondering whether you can generalize it
further, making the container type a template parameter. There's probably
a better way than this, but here's a version that works for both vectors
and deques, at least:

I also tried this, but was too stupid. Your approach seems to work for all
container types in the STL, which is quite enough, I think.

One problem may be, that the constructors need to be adjusted for other
types. But I don't see how this could be generalized.

Emanuel
 
E

Emanuel Ziegler

Thorsten said:
Do you still think that about the current library?

It is nearly the same as my idea, but much better implemented. You convinced
me.

Emanuel
 

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,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top