9 Replies - 1654 Views - Last Post: 11 August 2008 - 06:28 PM Rate Topic: -----

#1 The Architect 2.0  Icon User is offline

  • D.I.C Regular

Reputation: 37
  • View blog
  • Posts: 351
  • Joined: 22-May 08

generic member variables in a nongeneric class

Posted 10 August 2008 - 01:47 AM

anyhow, i have a problem. i didn't notice it earlier because i was using typedefs....but w/e

basically, my class looks similiar to this:
class DS
{   
private:
   //yada yada yada
   set<Node<T>>
public:
  //yada yada yada
}



the important thing is the set(obviously). i will have several 'parallel' sets that will be instantiated at runtime, each which can hold a node which can hold any type of object. each set will only hold nodes of the same template instance, but different sets will be holding different node template instances.

basically, i need a way to allow a non-generic class to have a generic member variable.

Is This A Good Question/Topic? 0
  • +

Replies To: generic member variables in a nongeneric class

#2 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: generic member variables in a nongeneric class

Posted 10 August 2008 - 08:56 AM

That's not possible, since the size of a class must be known at compile time (Which means that the size and number of its data members must also be known at compile time). Template classes are like incomplete "ghost" types; The concrete types are instantiated at compile time when their complete type information is known. There's no such thing as a run-time template, since a data type cannot change at run time.

Perhaps you could give a broader view of the context in which this problem appears in your program, and what you're trying to do here; someone may be able to offer a different kind of solution

This post has been edited by Bench: 10 August 2008 - 09:01 AM

Was This Post Helpful? 0
  • +
  • -

#3 The Architect 2.0  Icon User is offline

  • D.I.C Regular

Reputation: 37
  • View blog
  • Posts: 351
  • Joined: 22-May 08

Re: generic member variables in a nongeneric class

Posted 10 August 2008 - 11:17 AM

class DS  
{
typedef set<Node<T>> Column
typedef map<String, Column> ColumnCollection
private:  
   //yada yada yada  
   ColumnCollection colcollect
public:  
   //yada yada yada  
}



how this works is that each column is stored in the 'ColumnCollection' and each column can hold its own type. the user will be able to create Columns that hold a datatype of their choosing at runtime.

basically, the requirements are:
-the column's value_type is determined at runtime
-every columns' value_type CAN be unique(although it does not HAVE TO be)
-all columns can be stored together in a ColumnCollection
-ColumnCollection can be stored as a member variable in a non-generic class


if anyone has any ideas, that would be awesome :D
Was This Post Helpful? 0
  • +
  • -

#4 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2250
  • View blog
  • Posts: 9,245
  • Joined: 18-February 07

Re: generic member variables in a nongeneric class

Posted 10 August 2008 - 03:55 PM

pointers.

Generics are useful for designing and API -- but inside a program (once you are outside the control of a compiler) they must all have been resolved. i.e. Generics are for compile time use, NOT for runtime use.

So really what you are asking about is just plane old polymorphism.
Was This Post Helpful? 0
  • +
  • -

#5 The Architect 2.0  Icon User is offline

  • D.I.C Regular

Reputation: 37
  • View blog
  • Posts: 351
  • Joined: 22-May 08

Re: generic member variables in a nongeneric class

Posted 10 August 2008 - 04:17 PM

i'm not quite following...

the base issue is that i need to add both 'set<Node<int>' and 'set<Node<String>>'(both of which are columns) to the ColumnCollection container(a container to hold columns) - defined as 'map<String, Column>.' But because columns holding different node instances have different signatures(or w/e the proper term is), then i can't add them into the same ColumnCollection.*


*at least this is what i've been taught
Was This Post Helpful? 0
  • +
  • -

#6 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2250
  • View blog
  • Posts: 9,245
  • Joined: 18-February 07

Re: generic member variables in a nongeneric class

Posted 10 August 2008 - 09:48 PM

So you make a base class called Column, then you make two derived classes StringColumn and IntColumn. Tada...

But this leads to one problem, when storing them into the map you will have a problem since they are different classes (it will let you make a map<string, Column> but when you put the different types in you will have problems).

So you need to make the map use pointers: map<stirng, Column *>
Was This Post Helpful? 0
  • +
  • -

#7 The Architect 2.0  Icon User is offline

  • D.I.C Regular

Reputation: 37
  • View blog
  • Posts: 351
  • Joined: 22-May 08

Re: generic member variables in a nongeneric class

Posted 10 August 2008 - 10:06 PM

so theres no way to generalize it(so that the user can put in ANY type?)?
Was This Post Helpful? 0
  • +
  • -

#8 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: generic member variables in a nongeneric class

Posted 11 August 2008 - 01:20 AM

Here's the problem - data types are purely High-level language concepts (as are classes/structs and any kinds of meta-programming code used to generate them, such as templates). Once your code is compiled, all of this ceases to exist entirely - the machine code is all about pointers and arrays of bytes.

For example, if some struct in your program were 10 bytes, then in order to represent an object in your program, the machine code would contain an array of 10 bytes, which would be pushed on to the stack, and referred to in your program using a pointer. As you're probably aware, arrays have their sizes hard-wired into the machine code, because the CPU needs to know the exact offset of the start and end of the data on the stack.

What you're asking for is to write code where the types (and therefore the size of the types) are indefinite. Since its not possible to put indefinite values in machine code, there's absolutely no way that the CPU could know the location and size of each data element on the stack in order to access the data

The alternative is to rewrite your program using void pointers and a runtime 'flag' which identifies a data type by some arbitrary value. the sizeof a void pointer and sizeof the flag will be constant, so you can store those in a container. Then you can dynamically create objects of whatever size you like, with the runtime type flag attached to each object, which you will need to use every time you access the data to convert into something meaningful to your program.

This is a dangerous way to do things - essentially the you would be circumventing the safe environment of the C++ type system entirely and doing everything yourself without its help

This post has been edited by Bench: 11 August 2008 - 01:57 AM

Was This Post Helpful? 0
  • +
  • -

#9 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2250
  • View blog
  • Posts: 9,245
  • Joined: 18-February 07

Re: generic member variables in a nongeneric class

Posted 11 August 2008 - 12:41 PM

View PostThe Architect 2.0, on 10 Aug, 2008 - 10:06 PM, said:

so theres no way to generalize it(so that the user can put in ANY type?)?


Yes and no. You can create a new template class for columns. So you would have to instantiate a column something like column<int>, or column<Item>. So you will probably want to create a factory class to create the various objects.

So again, you have a base class called column, and then you have subclasses created by templates, then you have a factory method that returns a pointer to a column, but you can pass in an argument to tell it which type of column to create (column<int>, column<string> etc.). But this is still not totally open.

Now I assume that there is only a finite number of types that you would want your columns to be in. we could still use a factory method to make this even MORE general but here we begin to approach the complexity of creating a programming language (i.e. we need an infrastructure to describe object and how they are laid out in memory, and how you can access their member functions and data).

Remember you CAN do anything the computer is capable of doing... but sometimes it is not worth the effort (sometimes it is).

You can not use something like in Java where you may say column<?> or column<? super Object> since templates are delt with at COMPILE time not run time, Java has more leeway since it runs in a VM and can setup the column class during runtime (which you can do in C++ if you are willing to write your own object management infrastructure).
Was This Post Helpful? 0
  • +
  • -

#10 perfectly.insane  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 70
  • View blog
  • Posts: 644
  • Joined: 22-March 08

Re: generic member variables in a nongeneric class

Posted 11 August 2008 - 06:28 PM

I would think that the easiest way of achieving such would be to create a variant class (that represents a value, which may be internally of many types). It would be similar to the VARIANT type on Windows, but you can make it much easier to use.

Then, if you need a constraint that requires the columns to be homogeneous, you can create a column class that holds an array/list of variants, and performs a runtime check on the type contained within the variant).

So perhaps something like:

class variant {
public:
    typedef enum {
        vt_integer, vt_float, vt_string, .... } data_type;
    
    void set(int var) { type_ = vt_integer; val_int = var; }
    void set(float var) { type_ = vt_float; val_float = var; }
    void set(const std::string& var) { type_ = vt_string; val_string = var; }

    data_type typeof() const { return type_; }

...
...
};

class column {
public:
    column(variant::data_type constraint) : constraint_(constraint) { }
    void add(const variant& var) { if(var.typeof() != constraint_) { do something to indicate error } else { seq_.push_back(var); } }
....
....
private:
    seq<variant> seq_;
};



Was This Post Helpful? 0
  • +
  • -

Page 1 of 1