Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Template instantiation question

Reply
Thread Tools

Template instantiation question

 
 
Jonathan Mcdougall
Guest
Posts: n/a
 
      11-07-2005
mlimber wrote:
> Jonathan Mcdougall wrote:
> > mlimber wrote:

> [snip]
> > > I also tried eliminating m_registered altogether and having the
> > > constructor perform registration to no avail:
> > >
> > > DefaultCreationPolicy()
> > > {
> > > const bool success = theFactory::Instance().Register(
> > > ConcreteClass::GetID(), ConcreteClass::Create );
> > > assert( success );
> > > }

> >
> > This won't work. DefaultCreationPolicy is never instantiated. All you
> > use is static member functions and data and static member typedefs.

>
> Right, just as I indicated it wouldn't.
>
> > > Thanks for your efforts. Any other ideas?

> >
> > Well, I don't think my suggestion was a "maintenance hassle", since you
> > only have to derive from a_concrete_class instead of three different
> > classes. It is also less typing.
> >
> > template <class Abstract, class Derived, int id>
> > struct a_concrete_class
> > : Abstract,
> > AssignID<id>,
> > DefaultCreationPolicy<Abstract, Derived>
> > {
> > a_concrete_class()
> > {
> > DefaultCreationPolicy<Abstract, Derived>::IsRegistered();
> > }
> > };
> >
> > struct Derived1
> > : a_concrete_class<MyBase, Derived1, DERIVED_1>
> > {
> > Derived1()
> > {
> > }
> > };
> >
> > a_concrete_class never changes. I don't see where the hassle is.

>
> Oh, sorry. I didn't look closely enough. Your suggestion isn't the
> maintenance hassle I made it out to be, but unfortunately it doesn't
> solve the problem on VC++ 6 (sp6) or g++ 3.4.1: Derived1 and Derived2
> aren't registered with the factory, implying that the call to
> IsRegistered() is still optimized away.


Well, I don't have Visual C++ 6, so I cannot test. The goal here is to
"trick" the optimizer which shouldn't be that difficult with this
compiler

Perhaps something with pointers to member functions in
a_concrete_class: add a dummy member function which calls
IsRegistered(), get a pointer to it in the constructor, call
a_concrete_class::bar() which calls the member function through the
pointer, or something like that. Separating the class definition from
member function definitions could also help by making it more opaque to
the compiler. Maybe if Greg Comeau comes around this thread, he'll be
able to give you nifty tricks to baffle a compiler

> (FYI, the two compilers I need to get this to work on are VC++ 6 and
> Texas Instrument's TMS320C6x C/C++ Compiler v5.1.0. I'm just using g++
> because it's more convenient than TI's and more compliant that VC6.)


[Un]fortunately (depending on the pov), I've been working professionaly
only on g++ and Visual C++ 7.0 and it's been a while since I used 6.0,
so I cannot help much more here.

I think this is the kind of situation where you are getting towards the
limits of the language. IMO, going farther will only make it less
portable. I think you're in for some "maintenance hassle".


Jonathan

 
Reply With Quote
 
 
 
 
Jonathan Mcdougall
Guest
Posts: n/a
 
      11-07-2005
Kaz Kylheku wrote:
> mlimber wrote:
> > Right: the non-trivial initializer is the sticking point. Is this
> > behavior regulated by the Standard? (Jonathan suggests not in his
> > previous response.)


It is not.

> > > Speaking of which, can't you put the reference to m_registered into the
> > > template's constructor?
> > >
> > > template<class AbstractClass, class ConcreteClass>
> > > class DefaultCreationPolicy
> > > {
> > > public:
> > > // How about this!!
> > > DefaultCreationPolicy()
> > > {
> > > (void) IsRegistered(); // touch that static member
> > > }
> > >
> > > static AbstractClass* Create()
> > > // ... etc ..
> > >
> > > Since the constructor is called somewhere, it drags in the dependency
> > > on IsRegistered.

> >
> > Unfortunately, It doesn't seem to work on VC++ 6 or gnu 3.4.1 whether
> > or not the constructor is inline.

>
> Interesting. It seems that they realize that IsRegistered() does
> ``nothing''. After all, it only accesses a non-volatile variable and
> throws away the result. Hey, since nothing else uses that variable, why
> not throw it away---initializer with side effects be damned!
>
> (I wonder if declaring that static member volatile would change the
> behavior, hmm!)


No, volatile is a runtime feature, not compile-time. Optimization still
takes place.

> In any case, you can do your own initialization, instead of relying on
> the static variable's initializer.
>
> Just replace the (void) IsRegistered() with EnsureRegistration().
> EnsureRegistration() actually does something like this:
>
> if (!s_registered)
> s_registered = <the call to do the registration>;
>
> A bit of construction-time overhead to check the flag, but hopefully,
> the compiler won't throw this away.


It will, very probably. Silly optimizers


Jonathan

 
Reply With Quote
 
 
 
 
mlimber
Guest
Posts: n/a
 
      11-08-2005
Jonathan Mcdougall wrote:
> mlimber wrote:

[snip]
> > Oh, sorry. I didn't look closely enough. Your suggestion isn't the
> > maintenance hassle I made it out to be, but unfortunately it doesn't
> > solve the problem on VC++ 6 (sp6) or g++ 3.4.1: Derived1 and Derived2
> > aren't registered with the factory, implying that the call to
> > IsRegistered() is still optimized away.

>
> Well, I don't have Visual C++ 6, so I cannot test. The goal here is to
> "trick" the optimizer which shouldn't be that difficult with this
> compiler
>
> Perhaps something with pointers to member functions in
> a_concrete_class: add a dummy member function which calls
> IsRegistered(), get a pointer to it in the constructor, call
> a_concrete_class::bar() which calls the member function through the
> pointer, or something like that. Separating the class definition from
> member function definitions could also help by making it more opaque to
> the compiler. Maybe if Greg Comeau comes around this thread, he'll be
> able to give you nifty tricks to baffle a compiler


Well, after tinkering with it for far too long, it seems that the best
option for my compilers is simply to use a virtual function (in
particular, a virtual destructor):

virtual ~DefaultCreationPolicy()
{ if( !m_registered ) exit( -1 ); }

The TI compiler, but not VC6, is "smart" enough to figure out that
"(void) IsRegistered();" in the virtual destructor should still be
eliminated, and so I need some other non-trivial usage of m_registered
to prevent that. I would use an assert, but I don't want the behavior
to change if/when debugging mode is disabled. Hence, I hand-rolled an
equivalent. Unfortunately, this carries with it the baggage of a
virtual table, but in the real application that shouldn't be an issue.
I'm open to other suggestions, but that solves the problem for now.

Thanks for all your help, Jonathan and Kaz.

Cheers! --M

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Explicit instantiation of non-template member of template class Noah Roberts C++ 6 02-02-2011 09:53 PM
Instantiation of template method in template class Ed C++ 1 08-27-2008 06:41 AM
Explicit instantiation of STL vector demands explicit instantiation of all the templates it using internally. krunalbauskar@gmail.com C++ 1 12-25-2006 03:51 PM
explicit instantiation of template methods of template classes Thomas Maier-Komor C++ 6 05-19-2005 08:00 AM
Explicit template instantiation from template function doesn't compile? Fernando Cuenca C++ 4 09-06-2004 04:06 PM



Advertisments