JREF Homepage Swift Blog Events Calendar $1 Million Paranormal Challenge The Amaz!ng Meeting Useful Links Support Us
James Randi Educational Foundation JREF Forum
Forum Index Register Members List Events Mark Forums Read Help

Go Back   JREF Forum » General Topics » Computers and the Internet
Click Here To Donate

Notices


Welcome to the JREF Forum, where we discuss skepticism, critical thinking, the paranormal and science in a friendly but lively way. You are currently viewing the forum as a guest, which means you are missing out on discussing matters that are of interest to you. Please consider registering so you can gain full use of the forum features and interact with other Members. Registration is simple, fast and free! Click here to register today.

Tags template

Reply
Old 1st December 2006, 05:06 PM   #1
JamesM
Graduate Poster
 
JamesM's Avatar
 
Join Date: Mar 2002
Posts: 1,823
C++ template question

I've been messing about with recursive template classes. Here's something I don't get. The code below shows a template with a recursively defined static const member.

Code:
#include <iostream>
using namespace std;

template<int n> struct Recursive {
    static const Recursive<n-1> r;
    static const int val = n;
    public:
    Recursive() {
        cout << "Recursive<" << n << ">()" << endl;
    }
    void foo() const {
        cout << val << " ";
        r.foo();
    }

};

template <int n> const Recursive<n-1> Recursive<n>::r;

template<> struct Recursive<0> {
    static const int val = 0;
    public:
    Recursive() {
        cout << "Recursive<0>()" << endl;
    }
    void foo() const {
        cout << val << endl;
    }
};


int main() {
    Recursive<12> rec;
    //rec.foo();
}
When I run the code, I'm expecting to see the static members get initialised first, calling each other recursively, then the Recursive<12> at file scope. But all I see is:
Code:
Recursive<12>()
When I uncomment the call to foo() I get what I expect:
Code:
Recursive<11>()
Recursive<10>()
Recursive<9>()
Recursive<8>()
Recursive<7>()
Recursive<6>()
Recursive<5>()
Recursive<4>()
Recursive<3>()
Recursive<2>()
Recursive<1>()
Recursive<0>()
Recursive<12>()
12 11 10 9 8 7 6 5 4 3 2 1 0
Is this a compiler optimisation or something, or is it some property of static template classes? Non-template static classes seem to get initialised whether my code needs to call them or not.

I don't actually know how to turn off optimisation on gcc (or even if any optimisation is on by default), to test my hypothesis, so I throw myself upon the good offices of you, the C++ street smart reader. I promise to be suitably impressed by your knowledge.
__________________
"When we type away on discussion boards and post comments on our blogs, it feels like we’re sitting outside a pub in the evening sunshine with our attractive, cool friends – but we aren’t. That’s something we used to do before we got addicted to the internet." - Jon Ronson
JamesM is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 1st December 2006, 05:42 PM   #2
a_unique_person
Director of Hatcheries and Conditioning
 
a_unique_person's Avatar
 
Join Date: Jul 2002
Location: Mt Disappointment
Posts: 33,344
I suggest you make a human sacrifice to Satan and ask him, since C++ templates are the work of the devil.
__________________
Continually pushing the boundaries of mediocrity.
Everything is possible, but not everything is probable.
For if a man pretend to me that God hath spoken to him supernaturally, and immediately, and I make doubt of it, I cannot easily perceive what argument he can produce to oblige me to believe it. Hobbes
a_unique_person is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 1st December 2006, 08:56 PM   #3
69dodge
Illuminator
 
Join Date: Nov 2002
Posts: 3,607
I think the compiler is doing the right thing.

The C++ standard says, in section 14.7.1, paragraph 1:
Quote:
Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
It makes some sense, when you think about it. A static member of a class has nothing to do with any of the class's instances, really. For example, a static member of a non-template class gets initialized whether or not any instances of the class do. On the other hand, it wouldn't be a good idea for a static member of a class template to get initialized whether or not any instances of the class template do, because then you'd need to initialize a separate static member for every possible template argument. But the initialization of static members remains independent of class instances; it's just that for templates, it never happens (unless needed) instead of always happening. Much like all templates, which get instantiated only when needed.

Still, a_unique_person might not be so far off. Here is section 14.7.3, paragraph 7 of the standard:
Quote:
The placement of explicit specialization declarations for function templates, class templates, member functions of class templates, static data members of class templates, member classes of class templates, member class templates of class templates, member function templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, member class templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
(No, I'm not making this up; it really says that.)
69dodge is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 1st December 2006, 11:10 PM   #4
marting
Muse
 
marting's Avatar
 
Join Date: Sep 2003
Location: Rancho Santa Fe
Posts: 734
69dodge,

Quite right. I verified the same results with MSFT 2005. Optimization makes no difference, foo() forces recursive instantiation hence the constructors are executed per the standard.

Templates are powerful but at times invoke a lot of cursing so unique person may have a point. Never underestimate the power of the dark side.
__________________
Flying's easy. Walking on water, now that's cool.
marting is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 2nd December 2006, 07:28 AM   #5
Paul C. Anagnostopoulos
Nap, interrupted.
 
Paul C. Anagnostopoulos's Avatar
 
Join Date: Aug 2001
Location: a little toolshed
Posts: 18,592
Just to summarize:

Originally Posted by AUP
I suggest you make a human sacrifice to Satan and ask him, since C++ templates are the work of the devil.
Evidence:
Quote:
Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
Quote:
The placement of explicit specialization declarations for function templates, class templates, member functions of class templates, static data members of class templates, member classes of class templates, member class templates of class templates, member function templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, member class templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
~~ Paul
__________________
Millions long for immortality who do not know what to do with themselves on a rainy Sunday afternoon. ---Susan Ertz

RIP Mr. Skinny
Paul C. Anagnostopoulos is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 2nd December 2006, 08:22 AM   #6
JamesM
Graduate Poster
 
JamesM's Avatar
 
Join Date: Mar 2002
Posts: 1,823
69dodge, I am indeed impressed. Your explanation makes sense. Thanks.

Templates are indeed scary. But Alexandrescu's Modern C++ Design arrived this morning, and I have ordered Czarnecki and Eisenecker's Generative Programming, so I need to limber up before I tackle them...
__________________
"When we type away on discussion boards and post comments on our blogs, it feels like we’re sitting outside a pub in the evening sunshine with our attractive, cool friends – but we aren’t. That’s something we used to do before we got addicted to the internet." - Jon Ronson
JamesM is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 3rd December 2006, 08:01 AM   #7
69dodge
Illuminator
 
Join Date: Nov 2002
Posts: 3,607
Originally Posted by Paul C. Anagnostopoulos View Post
Just to summarize:

Evidence:
Most of it is just standard standardese, I figure.

The limerick at the end, though, is not the sort of thing one would expect to find in an international standard.
69dodge is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 3rd December 2006, 03:24 PM   #8
Paul C. Anagnostopoulos
Nap, interrupted.
 
Paul C. Anagnostopoulos's Avatar
 
Join Date: Aug 2001
Location: a little toolshed
Posts: 18,592
I'm sorry, but an object oriented programming language originally designed so that it could be implemented as a preprocessor is just not right.

~~ Paul
__________________
Millions long for immortality who do not know what to do with themselves on a rainy Sunday afternoon. ---Susan Ertz

RIP Mr. Skinny
Paul C. Anagnostopoulos is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 4th December 2006, 01:29 AM   #9
Stimpson J. Cat
Graduate Poster
 
Stimpson J. Cat's Avatar
 
Join Date: Sep 2001
Location: Oxford, UK
Posts: 1,833
Pual,

Quote:
I'm sorry, but an object oriented programming language originally designed so that it could be implemented as a preprocessor is just not right.
I'm not sure if you're referring to templates here specifically, or to the original implementation of C++ as a converter to C code here, but either way I do not think that this is a fair characterization.

In terms of templates, they aren't even really an essential part of the object oriented nature of C++. The ability of C++ to be used (effectively) as an object oriented language comes from class inheritance and virtual member functions. Templates are mostly for purposes of code re-use, and are very useful even in a completely non-object oriented context. In fact, most of my C++ programs are procedural, rather than object oriented, but I still use templates quite extensively.

In terms of the original Cfront implementation of C++, this was not so much a preprocessor as a code translator. I could be wrong, but my understanding of it is not that C++ was designed so that it could be implemented in terms of a front-end converter to C, but rather it was designed to be a super-set of C, and to be (almost) completely backwards compatible with C. That said, it makes sense that such a language would initially be implemented as a converter to C.

Anyway, I don't think templates are so bad. I think that like much of the complaints against C++, the arguments against templates mostly amount to the misguided notion that if a feature is there, you must use it. Anything you can do in C you can do in exactly the same way in C++ (with trivial exceptions of a few details involving type casting). So the only time a C++ programmer should ever find himself doing something differently in C++ than he would in C, is if there is some tangible benefit to doing it that way. If a programmer finds that the way he does things in C++ is somehow not an improvement on how he would do it in C, then the problem lies with the programmer, not the language.


Of course, one could argue that C++ is not an ideal object oriented language because it was not designed from the ground up to be object oriented, and if all you do is object oriented programming, then C++ may not be the best choice. But for me, this is actually a strength. C++ is not really so much an object oriented language, but rather a generic language which can be used for object oriented or procedural programming. In principle, any language can be used for either purpose, but they are usually so highly geared towards one as to make using it for the other purpose a complete nightmare. In my opinion, C++ does a very nice job of bridging the gap, allowing for a single language which not only does both jobs very well, but also allows for extremely easy integration of both types of programming into a single project.


Dr. Stupid
__________________
A poke in the eye makes Baby Jesus cry.
Stimpson J. Cat is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 4th December 2006, 03:19 AM   #10
a_unique_person
Director of Hatcheries and Conditioning
 
a_unique_person's Avatar
 
Join Date: Jul 2002
Location: Mt Disappointment
Posts: 33,344
I think the evidence is in the application. The C++ doco itself admits that the correct use of templates becomes pretty incomprehensible.
__________________
Continually pushing the boundaries of mediocrity.
Everything is possible, but not everything is probable.
For if a man pretend to me that God hath spoken to him supernaturally, and immediately, and I make doubt of it, I cannot easily perceive what argument he can produce to oblige me to believe it. Hobbes
a_unique_person is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 4th December 2006, 05:29 AM   #11
Paul C. Anagnostopoulos
Nap, interrupted.
 
Paul C. Anagnostopoulos's Avatar
 
Join Date: Aug 2001
Location: a little toolshed
Posts: 18,592
Originally Posted by Stimpy
Of course, one could argue that C++ is not an ideal object oriented language because it was not designed from the ground up to be object oriented, and if all you do is object oriented programming, then C++ may not be the best choice.
I don't demand a completely object-oriented language. I just think C++ is a bit of a hack. First, it had to be implemented as a preprocessor. Second, it was fairly early on in the days of object-oriented langauges, and we've learned some things. Third, it continued the culture of hacks in C, beginning with the base language itself. Not that I haven't earned my share of money programming in C, mind you.

But I have a stilted view of it anyway, since 90% of my experience with it was trying to write generators that could produce C++ from higher-level specifications. It was hell.

~~ Paul
__________________
Millions long for immortality who do not know what to do with themselves on a rainy Sunday afternoon. ---Susan Ertz

RIP Mr. Skinny
Paul C. Anagnostopoulos is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 4th December 2006, 06:59 AM   #12
JamesM
Graduate Poster
 
JamesM's Avatar
 
Join Date: Mar 2002
Posts: 1,823
Originally Posted by Stimpson J. Cat View Post
In terms of templates, they aren't even really an essential part of the object oriented nature of C++.
I think they are. Witness the proliferation of container classes before the STL was added to the standard library. Without a base Object class that all other classes extend from (like Smalltalk, ObjC/Cocoa and Java do), containers can't be responsible for memory management of what they contain, as void* types (the rough C-equivalent of a generic 'object') can't call virtual destructors. Templates get round this nicely.

I would welcome being corrected on this point, if there is an alternative.
__________________
"When we type away on discussion boards and post comments on our blogs, it feels like we’re sitting outside a pub in the evening sunshine with our attractive, cool friends – but we aren’t. That’s something we used to do before we got addicted to the internet." - Jon Ronson
JamesM is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 17th December 2006, 03:42 PM   #13
jeremyp
Thinker
 
Join Date: Aug 2003
Location: Reading, UK
Posts: 223
Originally Posted by JamesM View Post
I think they are. Witness the proliferation of container classes before the STL was added to the standard library. Without a base Object class that all other classes extend from (like Smalltalk, ObjC/Cocoa and Java do), containers can't be responsible for memory management of what they contain, as void* types (the rough C-equivalent of a generic 'object') can't call virtual destructors. Templates get round this nicely.

I would welcome being corrected on this point, if there is an alternative.
Yes, well, you said it yourself:

"Without a base Object class..."

Although it has to be said that even with a base object class, Java has been forced to introduce a limited version of templating.
jeremyp is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 17th December 2006, 03:56 PM   #14
jeremyp
Thinker
 
Join Date: Aug 2003
Location: Reading, UK
Posts: 223
[quote=Paul C. Anagnostopoulos;2145985I just think C++ is a bit of a hack. First, it had to be implemented as a preprocessor.[/quote]
You are confusing the language with the implementation. It's nonsense to suggest a language is a hack just because it was first implemented as a preprocessor for some other compiler. Objective-C was first implemented as a C preprocessor and that's a lovely language. C itself was first implemented as a Macro-11 preprocessor and the implementation I use now (gcc) is implemented as a preprocessor for whatever assembler runs on your target architecture.

Quote:
Second, it was fairly early on in the days of object-oriented langauges, and we've learned some things.
Um, no. Smalltalk predates C++ by a number of years and pretty much all the mistakes were made and learned from before C++ came along.

Quote:
Third, it continued the culture of hacks in C, beginning with the base language itself.
That's unarguable. The concept of C++ is a big hack, namely graft an object oriented framework onto another language (which is itself a hack).
jeremyp is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 19th December 2006, 01:30 AM   #15
a_unique_person
Director of Hatcheries and Conditioning
 
a_unique_person's Avatar
 
Join Date: Jul 2002
Location: Mt Disappointment
Posts: 33,344
Originally Posted by jeremyp View Post

Um, no. Smalltalk predates C++ by a number of years and pretty much all the mistakes were made and learned from before C++ came along.
Don't know about that. Inheritance is still a dead end, IMHO, as implemented in a hierarchical fashion, and multiple inheritance has been recognised already as a dead end.
__________________
Continually pushing the boundaries of mediocrity.
Everything is possible, but not everything is probable.
For if a man pretend to me that God hath spoken to him supernaturally, and immediately, and I make doubt of it, I cannot easily perceive what argument he can produce to oblige me to believe it. Hobbes
a_unique_person is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 19th December 2006, 10:48 AM   #16
Jekyll
Graduate Poster
 
Jekyll's Avatar
 
Join Date: Apr 2005
Location: The other other place
Posts: 1,589
Originally Posted by jeremyp View Post
That's unarguable. The concept of C++ is a big hack, namely graft an object oriented framework onto another language (which is itself a hack).
Doesn't that describe almost every OO language since smalltalk?
__________________
And I looked. And behold a green horse, and his name that sat on him was death. ~Tyndale New Testament
Jekyll is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 19th December 2006, 03:52 PM   #17
JamesM
Graduate Poster
 
JamesM's Avatar
 
Join Date: Mar 2002
Posts: 1,823
Originally Posted by a_unique_person View Post
Don't know about that. Inheritance is still a dead end, IMHO, as implemented in a hierarchical fashion, and multiple inheritance has been recognised already as a dead end.
The problem is not inheritance per se, but inheritance used without discipline, in lieu of more appropriate mechanisms being absent from a language. The problem is that inheritance does at least double-duty: code reuse and polymorphism.

MI is ok, as long as you have only one 'proper' class as the base class, and everything else is mixins. That works out tolerably in Python and C++, and at least in the latter you can differentiate between private and public inheritance. But there's no way to enforce such discipline in the language. I think Ruby's approach of single inheritance, but allowing mixins through modules, works the best of all the mainstream languages.
__________________
"When we type away on discussion boards and post comments on our blogs, it feels like we’re sitting outside a pub in the evening sunshine with our attractive, cool friends – but we aren’t. That’s something we used to do before we got addicted to the internet." - Jon Ronson
JamesM is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Old 29th December 2006, 07:05 PM   #18
jeremyp
Thinker
 
Join Date: Aug 2003
Location: Reading, UK
Posts: 223
Originally Posted by Jekyll View Post
Doesn't that describe almost every OO language since smalltalk?
Yep.

Well, every language I have come across, at least.

That doesn't mean the resulting language is necessarily useless or even bad.
jeremyp is offline   Quote this post in a PM   Nominate this post for this month's language award Copy a direct link to this post Reply With Quote Back to Top
Reply

JREF Forum » General Topics » Computers and the Internet

Bookmarks

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
Forum Jump


All times are GMT -7. The time now is 08:16 PM.
Powered by vBulletin. Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
© 2001-2012, James Randi Educational Foundation. All Rights Reserved.

Disclaimer: Messages posted in the Forum are solely the opinion of their authors.