Solved

compile time initialization of template class within template class

Posted on 2009-04-03
7
493 Views
Last Modified: 2012-05-06
I'd like to create an vector of the composite type sequence_of.  Within sequence_of there's a class controller.  The contoller class needs to instantiate at compile time iord_direct...  Microsoft .NET 2008 barfs (a window pops saying optimizing compiler has encountered a problem ..... tell microsoft etc. etc.) during compilation.  At issue:  How could I design the controller class such that I achieve the objective of being able to call a template class (iord_) within the template class (controller)?
# include <iostream>

# include <bitset>

# include <vector>

# include <string>
 

template <unsigned int size>

unsigned int iord_direct(unsigned int base, unsigned int offset);
 

// use this as example

template <>

unsigned int iord_direct<32>(unsigned int base, unsigned int offset) {

  //return __builtin_ldwio(__IO_CALC_ADDRESS_DYNAMIC(base, offset));

  return  0; 

}
 

template < typename UnsignedType > 

class controller 

{ 

  unsigned const size ; 

  unsigned const base ; 

  unsigned const offset ; 
 

  UnsignedType& a ; 

  //void get ( UnsignedType& a ) 

  //{

  //  UnsignedType xx = iord_direct < size > ( base, offset ) ; 

  //  a = xx ;

  //}

 // stuff 

public : 

  controller ( UnsignedType a_, unsigned size, unsigned base, unsigned offset ) 

  : a( a_) 

  , size   ( size ) 

  , base   ( base ) 

  , offset ( offset ) 

  {} 

  void get ( unsigned int ax ) 

  {

    UnsignedType xx = iord_direct < size > ( base, offset ) ;   //<<<<<E

    //a = xx ;

  }

}; 
 
 

struct sequence_of { 

  unsigned int mValue ; 

  controller < unsigned int > mwhatever; 

  sequence_of ( unsigned int size_, unsigned int base_addr_, unsigned int offset_  ) 

   : mValue    ( 0 ) 

   , mwhatever ( mValue, size_, base_addr_, offset_ ) 

  {} 
 

}; 
 
 

typedef std::vector < sequence_of* > SEQOF_VEC ; 
 

int main() { 

  SEQOF_VEC mSeqVec ; 

  int offset          = 0 ; 

  int const size      = 32;

  int const base_addr = 0x900000 ; 

  for ( int odx ( 0 ); odx < 30 ; ++odx ) { 

    mSeqVec.push_back ( new sequence_of ( size, base_addr,  offset  ) ) ; 

    offset += 2 ; 

  } 

  unsigned int zz = 4;

  mSeqVec [ 0 ]->mwhatever.get ( zz ) ;
 
 

}

Open in new window

0
Comment
Question by:forums_mp
  • 3
  • 3
7 Comments
 
LVL 40

Accepted Solution

by:
mrjoltcola earned 70 total points
Comment Utility
Before looking at your code, did you install VS 2008 service pack 2? Sounds like the compiler had an internal problem with your code.

As far as your code, you have place where you are trying to instantiate a template using a non-constant integer expression.


// Template parameters must be types or constants (known at compile time). size is dynamic, so cannot be generated

// at compile time, which is a requirement for templates, by definition. A constant, for example, would be 42

// In your code, size is actually a member of the surrounding class, which is set in a constructor. The compiler won't

// know what size equals until runtime, and even then, it will be differnet for each object, so C++ cannot instantiate

// a template using "size"
 

  void get ( unsigned int ax )

  {

    UnsignedType xx = iord_direct < size > ( base, offset ) ;   //<<<<<E   CANNOT USE size, it is not constant

    //a = xx ;

  }

Open in new window

0
 

Author Comment

by:forums_mp
Comment Utility
mrjoltcola:
Granted i'm away from my compiler rigth now, however, if I modified controller to account for size in the template argument list,  I still get an error from the compiler.  If memory serves the error is: 'illegal reference to non-static member' on base and offset..
# include <iostream>

# include <bitset>

# include <vector>

# include <string>

 

template <unsigned int size>

unsigned int iord_direct(unsigned int base, unsigned int offset);

 

// use this as example

template <>

unsigned int iord_direct<32>(unsigned int base, unsigned int offset) {

  //return __builtin_ldwio(__IO_CALC_ADDRESS_DYNAMIC(base, offset));

  return  0; 

}

 

template < typename UnsignedType, unsigned size > 

class controller 

{ 

  unsigned const base ; 

  unsigned const offset ; 

 

  UnsignedType& a ; 

  //void get ( UnsignedType& a ) 

  //{

  //  UnsignedType xx = iord_direct < size > ( base, offset ) ; 

  //  a = xx ;

  //}

 // stuff 

public : 

  controller ( UnsignedType a_, unsigned base, unsigned offset ) 

  : a( a_) 

  , base   ( base ) 

  , offset ( offset ) 

  {} 

  void get ( unsigned int ax ) 

  {

    UnsignedType xx = iord_direct < size > ( base, offset ) ;   //<<<<<E

    //a = xx ;

  }

}; 

 

 

struct sequence_of { 

  unsigned int mValue ; 

  controller < unsigned int, 32 > mwhatever; 

  sequence_of ( unsigned int base_addr_, unsigned int offset_  ) 

   : mValue    ( 0 ) 

   , mwhatever ( mValue, base_addr_, offset_ ) 

  {} 

 

}; 

 

 

typedef std::vector < sequence_of* > SEQOF_VEC ; 

 

int main() { 

  SEQOF_VEC mSeqVec ; 

  int offset          = 0 ; 

  int const base_addr = 0x900000 ; 

  for ( int odx ( 0 ); odx < 30 ; ++odx ) { 

    mSeqVec.push_back ( new sequence_of ( base_addr,  offset  ) ) ; 

    offset += 2 ; 

  } 

  unsigned int zz = 4;

  mSeqVec [ 0 ]->mwhatever.get ( zz ) ;

 

 

}

Open in new window

0
 
LVL 40

Assisted Solution

by:mrjoltcola
mrjoltcola earned 70 total points
Comment Utility
The code you just posted compiles fine with no errors GCC/G++, though I don't know that it runs. Check back when you are at your compiler.

Also, FYI VS 2008 Service Pack 2 is avail, do you have it installed? I just thought of it since you had an internal compiler error.


0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:forums_mp
Comment Utility
mrjoltcola::
|| Also, FYI VS 2008 Service Pack 2 is avail, do you have it installed? I
Probably not but I'll check!
While I have the code here (it's a shame this laptop doesnt have a compiler on it): I recalled a handful of errors if I opted to make the get function static.  Not following why?
0
 

Author Comment

by:forums_mp
Comment Utility
Apparently I didnt have service pack 2 installed.  Also tried a gcc compiler and the most recent version of the code worked.   What would be the workaround for a static get method?  The get method in the original source is static.  If i move to a non static alternative I get errors when I try to use std:cout on the object.

i.e
controller < unsigned int, 32 > mwhatever;
 std::cout << whatever << '\n';  //
0
 
LVL 40

Expert Comment

by:mrjoltcola
Comment Utility
I don't understand what your code does, so I cannot comment on why you need static vs non-static. I can definitely say its nothing to do with using cout.

Basically inside a static method, you don't have an "object" (or "this") in context, so you cannot access any instance variables. You can only access other static members from a static method. Be aware of what static means in this context, its essentially a global storage, but with a class namespace and access control. It works like a global function. You can allocate instances of the class inside the static method, but the static method cannot use this-> anything.

0
 
LVL 5

Assisted Solution

by:Kimpan
Kimpan earned 30 total points
Comment Utility
if iord_direct is supposed to take the byte- or bitsize of a specific type, you might use sizeof.

so get becomes if it is supposed to operate on UnsignedType:
  void get ( unsigned int ax )
    {
        UnsignedType xx = iord_direct < sizeof(UnsignedType) * 8 > ( base, offset ) ;   //<<<<<E
        //a = xx ;
    }

better would be to make iord_direct take a type

template<typename T>
unsigned int iord_direct(unsigned int base, unsigned int offset)
{
    enum { BITSIZE = sizeof(T) * 8  };  // compile-time operation
}
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now