469,926 Members | 1,575 Online

# Can I dynamically create vectors of multiple depths?

This actually compiles and works but it doesn't seem like the best
code, so I was wondering is there another way to do this?

Expand|Select|Wrap|Line Numbers
1. template <typename Tvector<T>* addDepth(T)
2. {
3. return new vector<T>;
4. }
5.
6. ....a templated meth...
7. {
8. //Create multi-depth vector based on length
9. void* vec;
10. int length = getLength( obj );
11. for ( int i = 0; i < length; i++ )
12. {
13. vec = addDepth( someValue );
14. }
15.
16. vector<T2>* b = ( vector<T2>* ) vec;
17. }
18.
19.
Jun 27 '08 #1
7 1923
On Apr 13, 11:04*pm, Rob <someidunknown1...@yahoo.comwrote:
This actually compiles and works but it doesn't seem like the best
code, so I was wondering is there another way to do this?

Expand|Select|Wrap|Line Numbers
1. template <typename Tvector<T>* addDepth(T)
2. {
3. * * *return new vector<T>;
4. }
5. ...a templated meth...
6. {
7. * * *//Create multi-depth vector based on length
8. * * *void* vec;
9. * * *int length = getLength( obj );
10. * * *for ( int i = 0; i < length; i++ )
11. * * *{
12. * * * * * *vec = addDepth( someValue );
13. * * *}
14. * * *vector<T2>* b = ( vector<T2>* ) vec;
15. }
16.
Whoops. I meant:

for ( int i = 0; i < length; i++ )
{
if ( i == 0 ) vec = addDepth( someValue );
else vec = addDepth( vec );
}
Jun 27 '08 #2
Rob wrote:
On Apr 13, 11:04*pm, Rob <someidunknown1...@yahoo.comwrote:
>This actually compiles and works but it doesn't seem like the best
code, so I was wondering is there another way to do this?

Expand|Select|Wrap|Line Numbers
1. template <typename Tvector<T>* addDepth(T)
2. {
3. return new vector<T>;
4. }
5. ...a templated meth...
6. {
7. //Create multi-depth vector based on length
8. void* vec;
9. int length = getLength( obj );
10. for ( int i = 0; i < length; i++ )
11. {
12. vec = addDepth( someValue );
13. }
14. vector<T2>* b = ( vector<T2>* ) vec;
15. }

Whoops. I meant:

for ( int i = 0; i < length; i++ )
{
if ( i == 0 ) vec = addDepth( someValue );
else vec = addDepth( vec );
}
What is the problem you want to solve? The code above has undefined behavior
in the casting and looses handles to allocated memory, which therefore
leaks. It is impossible to tell how to better solve your problem since the
problem cannot be deduced from the proposed solution.
Best

Kai-Uwe Bux
Jun 27 '08 #3
* Rob:
On Apr 13, 11:04 pm, Rob <someidunknown1...@yahoo.comwrote:
>This actually compiles and works but it doesn't seem like the best
code, so I was wondering is there another way to do this?

Expand|Select|Wrap|Line Numbers
1. template <typename Tvector<T>* addDepth(T)
2. {
3.      return new vector<T>;
4. }
5. ...a templated meth...
6. {
7.      //Create multi-depth vector based on length
8.      void* vec;
9.      int length = getLength( obj );
10.      for ( int i = 0; i < length; i++ )
11.      {
12.            vec = addDepth( someValue );
13.      }
14.      vector<T2>* b = ( vector<T2>* ) vec;
15. }

Whoops. I meant:

for ( int i = 0; i < length; i++ )
{
if ( i == 0 ) vec = addDepth( someValue );
else vec = addDepth( vec );
}
What do you mean by "works": what is the external effect that you have observed
and that you're pleased with?
- Alf
Jun 27 '08 #4
On Apr 14, 12:01*am, Kai-Uwe Bux <jkherci...@gmx.netwrote:
Rob wrote:
On Apr 13, 11:04*pm, Rob <someidunknown1...@yahoo.comwrote:
This actually compiles and works but it doesn't seem like the best
code, so I was wondering is there another way to do this?
Expand|Select|Wrap|Line Numbers
1. template <typename Tvector<T>* addDepth(T)
2. {
3. return new vector<T>;
Expand|Select|Wrap|Line Numbers
1.
2.
3.                 }
•
•
•
•                 ...a templated meth...
• {
• //Create multi-depth vector based on length
• void* vec;
• int length = getLength( obj );
• for ( int i = 0; i < length; i++ )
• {
• vec = addDepth( someValue );
• }
•
•
•
•                 vector<T2>* b = ( vector<T2>* ) vec;
•
•
•
•                 }
•
•
•
•
•
•
• Whoops. I meant:
* * *for ( int i = 0; i < length; i++ )
* * *{
* * * * * *if ( i == 0 ) vec = addDepth( someValue );
* * * * * *else vec = addDepth( vec );
* * *}

What is the problem you want to solve? The code above has undefined behavior
in the casting and looses handles to allocated memory, which therefore
leaks. It is impossible to tell how to better solve your problem since the
problem cannot be deduced from the proposed solution.

Best

Kai-Uwe Bux I want to be able to dynamically (at runtime) create a vector of
compile-time-unknown type. And the vector might be a vector of an int,
or a string or a vector of a vector of a string, etc. How would I do
that?
Jun 27 '08 #5
Rob wrote:
>
I want to be able to dynamically (at runtime) create a vector of
compile-time-unknown type. And the vector might be a vector of an int,
or a string or a vector of a vector of a string, etc. How would I do
that?
You can't.

std::vector is a template, you can only instantiate a template at
compile time.

The best you can do is use a the factory pattern to return vectors of
known types.

--
Ian Collins.
Jun 27 '08 #6
Rob <so***************@yahoo.comwrites:
On Apr 14, 12:01*am, Kai-Uwe Bux <jkherci...@gmx.netwrote:
>Rob wrote:
On Apr 13, 11:04*pm, Rob <someidunknown1...@yahoo.comwrote:
This actually compiles and works but it doesn't seem like the best
code, so I was wondering is there another way to do this?
>
Expand|Select|Wrap|Line Numbers
1. template <typename Tvector<T>* addDepth(T)
2. {
3. return new vector<T>;
Expand|Select|Wrap|Line Numbers
1.
2.                 >}
•
•
•                 >...a templated meth...
• {
• //Create multi-depth vector based on length
• void* vec;
• int length = getLength( obj );
• for ( int i = 0; i < length; i++ )
• {
• vec = addDepth( someValue );
• }
•
•
•                 >vector<T2>* b = ( vector<T2>* ) vec;
•
•
•                 >}
•
•
•                 >
•
•
• Whoops. I meant:
* * *for ( int i = 0; i < length; i++ )
* * *{
* * * * * *if ( i == 0 ) vec = addDepth( someValue );
* * * * * *else vec = addDepth( vec );
* * *}

What is the problem you want to solve? The code above has undefined behavior
in the casting and looses handles to allocated memory, which therefore
leaks. It is impossible to tell how to better solve your problem since the
problem cannot be deduced from the proposed solution.

Best

Kai-Uwe Bux
I want to be able to dynamically (at runtime) create a vector of
compile-time-unknown type. And the vector might be a vector of an int,
or a string or a vector of a vector of a string, etc. How would I do
that? You are wanting typed _values_, like in Lisp. You would do that by
applying Greenspun's Tenth Law.

Specifically, you would do:

#include <vector>
#include <iostream>
#include <string>
#include <iterator>
#include <fstream>

typedef enum { ttSymbol, ttCharacter, ttByte, ttInteger, ttString, ttVector } TypeTag;

class Object {
public:
virtual TypeTag getTypeTag(void)=0;
virtual void print(std::ostream& out)=0;
};

class Symbol:public Object {
private:
std::string name;
public:
virtual TypeTag getTypeTag(void){return ttSymbol;}
Symbol(std::string aName):name(aName){};
inline std::string getName(void){return name;}
virtual void print(std::ostream& out){out<<name;};
};

static Symbol* NIL=new Symbol("NIL");

class Character:public Object {
private:
char value;
public:
virtual TypeTag getTypeTag(void){return ttCharacter;};
Character(char aValue):value(aValue){};
inline char getChar(void){return value;};
virtual void print(std::ostream& out){ out.put(value); };
};

class Byte:public Object {
private:
char value;
public:
virtual TypeTag getTypeTag(void){return ttByte;};
Byte(char aValue):value(aValue){};
inline char getByte(void){return value;};
virtual void print(std::ostream& out){ out<<int(value); };
};

class Integer:public Object {
private:
int value;
public:
virtual TypeTag getTypeTag(void){return ttInteger;};
Integer(int aValue):value(aValue){};
inline int getInt(void){return value;};
virtual void print(std::ostream& out){ out<<value; };
};

class String:public Object {
private:
std::string value;
public:
virtual TypeTag getTypeTag(void){return ttString;};
String(std::string aValue):value(aValue){};
inline std::string& getString(void){return value;};
virtual void print(std::ostream& out){ out<<"\""<<value/*todo: escape " and \ in value*/<<"\""; };
};

class Vector:public Object {
private:
std::vector<Object*value;
public:
virtual TypeTag getTypeTag(void){return ttVector;};
Vector(int size=0,Object* initialElement=NIL):value(std::vector<Object*>(siz e,initialElement)){};
inline std::vector<Object*>& getVector(void){return value;};
virtual void print(std::ostream& out);
};

void Vector::print(std::ostream& out){
out<<"#(";
typedef std::vector<Object*>::iterator Iter;
Iter end=value.end();
for(Iter cur=value.begin();cur!=end;cur++){
if(cur!=value.begin()){
out<<" ";
}
(*cur)->print(out);
}
out<<")";
}

// Really, multidimentional arrays are another beast (ie class
// Array:public Object{ etc } than vectors, but here is how you can
// implement them with vectors of vectors, as you asked for this
// kind.

Vector* makeArray(std::vector<intdimensions,Object* initialValue){
if(dimensions.size()==0){
return NULL;
}
int firstDim=dimensions[0];
dimensions.erase(dimensions.begin());
Vector* result=new Vector();
if(dimensions.size()==0){
for(int i=0;i<firstDim;i++){
result->getVector().push_back(initialValue);
}
}else{
for(int i=0;i<firstDim;i++){
result->getVector().push_back(makeArray(dimensions,initia lValue));
}
}
return(result);
}

int main(void){
Vector* v=new Vector(1);
v->getVector().push_back(new Character('A'));
v->getVector().push_back(new Byte(65));
v->getVector().push_back(new Integer(42));
v->getVector().push_back(new String("Hello"));
int dims[] = {2,3,4};
std::vector<intvdims(dims,dims+sizeof(dims)/sizeof(dims[0]));
Vector* u=makeArray(vdims,new Integer(0));
v->getVector().push_back(u);

v->print(std::cout);
std::cout<<std::endl;
return(0);
}
/*
-*- mode: compilation; default-directory: "~/src/tests-c++/" -*-
Compilation started at Mon Apr 14 10:52:06

p=type-tag ; g++ -o \$p \$p.c++ && ./\$p
#(NIL A 65 42 "Hello" #(#(#(0 0 0 0) #(0 0 0 0) #(0 0 0 0)) #(#(0 0 0 0) #(0 0 0 0) #(0 0 0 0))))

Compilation finished at Mon Apr 14 10:52:07
*/

--
__Pascal Bourguignon__
Jun 27 '08 #7
pj*@informatimago.com (Pascal J. Bourguignon) writes:
>
You are wanting typed _values_, like in Lisp. You would do that by
applying Greenspun's Tenth Law.
"Greenspun's Tenth Rule of Programming: any sufficiently complicated C
or Fortran program contains an ad hoc informally-specified bug-ridden
slow implementation of half of Common Lisp."

- Philip Greenspun

"Including Common Lisp."

- Robert Morris

Nice example, though. You are doing your very best to convince all
these C++ programmers to try Lisp. You should explain the
correspondence between "functors" and the way Lambda works in a
lexically scoped Lisp, for example Scheme.

Chip

--
Charles M. "Chip" Coldwell