Hi everyone i'll keep it brief.Say i have

template <int k> struct A  {
   enum {key=k};
 };

template <int t> struct B  {
   std::vector <A<y>* > vec;
   B ()  {  
      vec.push_back (new A<y> ());
      B <t-1> ();
    }
 };

template <> struct B <0> {};

int main ()  {
   B <10> b;
 }

Now this works .. unless i define arguments for the B's constructor.I must create an array of objects each of which should contain a unique static integral member.
This works too:

template <int t> struct B  {
   std::vector <A<y>* > vec;
   int y;
   B (int x) : y(x)  {
      B <t> ();
    } 
   B ()  {  
      vec.push_back (new A<y> ());
      B <t-1> ();
    }
 };

But how should this be writeen ?

template <int t> struct B  {
   int y;
   std::vector <A<y>* > vec;
   B (/* int x */) : x(y) {  
      vec.push_back (new A<y> ());
      B <t-1> (/* what here? */); 
    }
 };

Recommended Answers

All 10 Replies

What do you want to achieve with this:

B () : x(y) {  
      B <t-1> (); // What do you think happens on this line?
}

The design currently makes very little sense.

Does the assignment specifically state 'array', if so then you probably are not allowed to use a vector.

Are you really trying to use meta-programming to create an array of site t?

firstPerson i'm just freshly acquainted to the technique but i realized by myself it doesn't work .. i'm struggling for some time to solve a problem but this is another dead end.. sorry for your time

Well if you want to stick through it and fight it, then we'll gladly try to assist. Just post your problem statement.

The basic problem in all the codes that you put is this line:

std::vector <A<y>* > vec;

This suggest that you are trying to instantiate a class template A with an integer variable y. This is impossible. All template arguments that are of some primitive type (like int) must be assigned to compile-time constants. This includes literal constants (like 3 or 42), enum values (like enum { value = 2 } ) or const variables (like a global constant or static const data member). Basically, it is like when you create static arrays, the value has to be resolvable at compile-time, and, of course, never change at run-time.

For the rest, I couldn't possibly give any advice, I have no idea what that code you posted is supposed to achieve.

Ok i have a class which declares an integer of enumeration type.I don't want a static const because it will be shared by all instances of that class and because i need it to be unique.It is in fact hierarchy of objects all of which are based on creating windows.Here is a brief description since the code goes for about 1000 lines:

template <unsigned long style,
          const char* type >
class WndObj  {
   static const char* editbox;
   static const char* staticbox;
   ~WndObj () {} 
   virtual void Create (); //creates a window
   //other virtual functions and constructors
 };
template <unsigned long,const char*> const char* WndObj <unsigned long,const char*> :: staticbox="static";
typedef WndObj <WS_GROUP|WS_DLGFRAME,WndObj<>::staticbox> Staticbox;
//other aliases

class Show : virtual protected Editbox  {
   Show () : Editbox () {}
   //overriding functions 
   //contains info about a show .. movie name .. hour .. duration etc
   //constructs an editbox in which an hour will be typed
 };

class ShowRow : virtual protected Editbox {
   //overriding functions 
   //holds a dynamic array of shows under a single name 
   //creates a schedule for a given show
 };
   
template <int i> class Hall : virtual protected Staticbox  {
   std::vector <ShowRow*> shr;
   enum {ID=i,ButtonAdd=i*10+1,ButtonRem=i*10+2// etc};
   void Create (); 
   void ChangeFont (HFONT hf) {
      for (std::vector<ShowRow*>::iterator i=shr.begin();i!=shr.end();++i)  {
         (*i)->ChangeFont(hf);
        } 
    }
   //buttons and other controls will get an individual id based on the 'i' template argument
   //this class would hold a dynamic array of ShowRows along with other buttons and windows that will be called in a switch statement in case of a WM_COMMAND message
 };

And finally i wanted to make it easier and also not to burden the main WndProc by creating an object say .. Booth .. which will hold a given number of Halls.
I knew all along that i was creating new types by doing Hall<1> Hall<2> etc so i know they won't fit in an array.Also the recursive constructor declared a vector with each instantiation thus creating a vector of size one each time.So what i need is to be able to create an array of a given size of type Hall , array in which each object could be assigned an individual static constant integer.

Why not just:

class A {
 static int currentID;
 int uid;

 public:
     A() : uid( currentID++ ) { }
};

int A::currentID = 0;

And you can just create the objects and put them in a vector, as long as you don't have multiple threads creating objects of A they will have a unique ID.

If this is not what you want, then it's still not very clear to me what the goal is.

I need a constat expression that can be evaluated in a swicth/case statement.What you suggest won't work.Believe me i'm trying to figure this out for two days.
This will work:

template <int i> struct A  {
   enum {ID=i};
   static const int uID=i; // this i can't use since it will be shared by all instances
   A ()  {
      switch (i) {
         case ID: break;
       }
    }
 };

First of all, this line:

template <unsigned long style, const char* type >

is not so good because you can use char* but should avoid using "char*" as a template argument. Make sure this is what you want and be careful when using it.

For your problem, again, I'm not sure I understand exactly. And I think you are confused between should and can be done at compile-time (with templates, classes, enums) and at run-time (with constructors, objects, etc.). If you want to create a list of objects of different type (i.e. different template arguments and ID), you can always use a tuple (from Boost.Tuple):

#include <boost/tuple/tuple.hpp>

template <int i> struct A {
  enum {ID=i};
  //..
};

boost::tuple< A<0>, A<1>, A<2>, A<3>, A<4> > myAlist;

If you want to construct that array at run-time (through a constructor or main function), that is impossible. The complete type (all the types contained in the tuple) has to be known at compile-time.

If you want a unique ID for each instance of the object, that requires a run-time process, thus, this is impossible via templates. Hence, don't dream of being able to have them as const values (compile-time constants, like the switch case requires).

If you want each object to have a unique ID that is const, they would have to each be of a unique type (which is not hard to do with templates and tuples). However, to use this ID outside of the class (i.e. object), would require dynamic binding (i.e. a virtual function binded at run-time) which invalidates the constness of the ID. However, if all you want is to be able to use that ID in methods internal to that object, then you would be able to do it. As so:

//have a base class (entry point of the dynamic binding).
struct Bar {
  //all methods as pure virtuals, for example:
  virtual void Foo(int j) = 0;
};

struct BarFactory {
  template <int i>
  struct BarImpl : public Bar {
    enum { ID=i };
    //all the virtual methods here, for example:
    void Foo(int j) {
      switch (j) {
        case ID: break; //this is OK, ID is a compile-time constant, even though Foo is binded at run-time.
      };
    };
  };

  struct start_result { typedef BarImpl<0>* type; };
  template <class T>
  struct result { }; //intentionally empty.
  template <int i>
  struct result< BarImpl<i> > { //template specialization
    typedef BarImpl< i+1 > type;
  };

  template <int i>
  static result< BarImpl<i> >::type* CreateNew(BarImpl<i>*) {
    return new result< BarImpl<i> >::type();
  };
  static start_result::type* CreateNew() {
    return new start_result::type();
  };
};

int main() {
  std::vector<Bar*> arr;

  typedef BarFactory::start_result::type BarImpl0;
  BarImpl0* ptr0 = BarFactory::CreateNew();
  arr.push_back(ptr0);

  typedef typename BarFactory::result<BarImpl0>::type BarImpl1;
  BarImpl1* ptr1 = BarFactory::CreateNew(ptr0);
  arr.push_back(ptr1);

  typedef typename BarFactory::result<BarImpl1>::type BarImpl2;
  BarImpl2* ptr2 = BarFactory::CreateNew(ptr1);
  arr.push_back(ptr2);

  //...
};

Of course, you can always do the above recursively as well, I'll let you figure that one out.

Thank you very much Mike and the rest of you guys.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.