From: brett@ada9x.enet.dec.com (Bevin R. Brett) Newsgroups: comp.lang.ada Subject: Ada and C++, as a learning language and as a comparison Date: 4 AUG 94 08:30:31 EST Organization: Digital Equipment Corporation I have been studying with intrique the C++ template feature. It is fascinating to understand the basic underlying concepts, and how they work together. Basic Concepts: --------------- Basically the templates definitions are parsed into syntax trees at the point they occur in the text, and then have SOME of their identifiers bound to declarations - but not all. There is no requirement for explicit instantiation. Instead the function template declarations are resolved against, using matching rules that are enhanced versions of the function [overloading] matching rules. Then an implicit specialization is generated to satisfy the call. The site of this generation differs between - the draft std, which says it happens before the containing global declaration, - cfront & DEC C++, which do it after the containing global declaration, - Borland C++, which does it at the end of the file scope containing the call. This is detectable, and it is relatively straight forward to write some C++ code which will compile under all three schemes, and call a different function under each scheme. Identifiers which were not bound in the template definition are bound in the instantiation, and all the semantic checking is now done. This means that the semantics may vary according to where the instantiation is done - and this is a non-diagnosible error according to the draft std - it violates the One Definition Rule. Furthermore in many compilation systems, one of the implicit instantiations is chosen at random by the linker. Teaching Problems: ------------------ To explain the behaviour of templates, students have to understand all about partially bound syntax trees! Templates provided as reusable components by instructors are very sensitive to the context where they are instantiated, and whose compiler is used. Error messages involving templates often come out miles from the source of the problem. S/W Engineering Problems: ------------------------- Templates are much closer to syntax-based macros than to Ada's semantically bound polymorphic algorithms. This makes it much more difficult ... (a) to know what the valid arguments to a template are, (b) to know what the result of a template instantiation is, (c) to know whether a template usage involves a non-diagnosable error, (d) to maintain code involving template instantiations (e) to maintain template definitions Summary: -------- I didn't realise how green the grass was on the Ada-"generic" side of the fence, until I looked closely at the "equivalent" feature in C++. /Bevin ================================================================================ ps: Here is an example of C++ templates (a single source file) that you can look at for yourself. template <class C> int tinner(C c) { return later1 + later2; } template <class C> int t(C c) { static_cnt1++; global_cnt1++; undecl_cnt1++; static_cnt2++; global_cnt2++; undecl_cnt2++; multiscope1++; multiscope2++; return c.x + tinner(c) + f0(); } struct S1 { int x; } s1; struct S2 { int y; } s2; struct S3 { char x[10]; } s3; static int static_cnt1 = 0; int global_cnt1 = 0; int multiscope1 = 0; int later1 = 0; int f0(){ struct S0 {int x;} s0; return t(s0); } int f1(){ return t(s1); } int f2(){ return t(s2); } int f3(){ return t(s3); } int f4(){ struct S4{int x;} multiscope2; return t(multiscope2); } static int static_cnt2 = 0; int global_cnt2 = 0; int multiscope2 = 0; int later2 = 0;