Can I dynamically create vectors of multiple depths?

R

Rob

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?

Code:
template <typename T> vector<T>* addDepth(T)
{
     return new vector<T>;
}

....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;
}
 
R

Rob

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?

Code:
template <typename T> vector<T>* addDepth(T)
{
     return new vector<T>;

}

...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 );
}
 
K

Kai-Uwe Bux

Rob said:
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?

Code:
template <typename T> vector<T>* addDepth(T)
{
return new vector<T>;

}

...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
 
R

Rob

Rob said:
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?
Code:
template <typename T> vector<T>* addDepth(T)
{
return new vector<T>; 
} 
...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?
 
I

Ian Collins

Rob said:
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.
 
P

Pascal J. Bourguignon

Rob said:
Rob said:
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?
Code:
template <typename T> vector<T>* addDepth(T)
{
return new vector<T>; [QUOTE]
}[/QUOTE]

...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 );
}[/QUOTE]
[QUOTE]
vector<T2>* b = ( vector<T2>* ) vec; [QUOTE]
}[/QUOTE]
[QUOTE]

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?[/QUOTE]

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::eek:stream& 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::eek:stream& 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::eek:stream& 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::eek:stream& 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::eek:stream& 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::eek:stream& 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*>(size,initialElement)){};
inline std::vector<Object*>& getVector(void){return value;};
virtual void print(std::eek:stream& out);
};

void Vector::print(std::eek:stream& 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<int> dimensions,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,initialValue));
}
}
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<int> vdims(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
*/
 
C

Charles Coldwell

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
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top