source: git/ntl/doc/tour-stdcxx.html @ 26e030

spielwiese
Last change on this file since 26e030 was de6a29, checked in by Hans Schönemann <hannes@…>, 19 years ago
* hannes: NTL-5.4 git-svn-id: file:///usr/local/Singular/svn/trunk@8693 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 17.3 KB
Line 
1<html>
2<head>
3<title>
4A Tour of NTL: Traditional and ISO Modes  </title>
5</head>
6
7<body bgcolor="#fff9e6">
8<center>
9<a href="tour-modules.html"><img src="arrow1.gif" alt="[Previous]" align=bottom></a>
10 <a href="tour.html"><img src="arrow2.gif" alt="[Up]" align=bottom></a> 
11<a href="tour-unix.html"> <img src="arrow3.gif" alt="[Next]" align=bottom></a>
12</center>
13
14<h1> 
15<p align=center>
16A Tour of NTL: Traditional and ISO Modes
17</p>
18</h1>
19
20<p> <hr> <p>
21
22<p>
23
24As of version 4.1,
25NTL can be compiled and used in one of two modes: Traditional or ISO.
26<i>As of NTL version 5.4, ISO mode is the default.</i>
27
28<p>
29To revert to traditional mode, you can pass <tt>NTL_STD_CXX=off</tt>
30as an argument to the configuration script
31when <a href="tour-unix.html">installing NTL on a Unix or Unix-like system</a>,
32which will unset the flag <tt>NTL_STD_CXX</tt> in the <tt>config.h</tt>
33file.
34Alternatively (and especially on non-Unix systems),
35you can unset this flag  by hand by editing
36the the <tt>config.h</tt> file.
37<p>
38
39
40
41<p>
42In Traditional mode, the NTL header files include the traditional
43<tt>C++</tt> header files <tt>&lt;stdlib.h&gt;</tt>,
44<tt>&lt;math.h&gt;</tt>, and <tt>&lt;iostream.h&gt;</tt>.
45These files declare a number of names (functions, types, etc.)
46in the <i>global namespace</i>.
47Additionally, the NTL header files declare a number of names,
48also in the global namespace.
49
50<p>
51In ISO mode, three things change:
52
53<ol>
54<li>
55<b>NTL namespace:</b>
56The NTL header files wrap all NTL names in a namespace, called <tt>NTL</tt>.
57
58<p>
59<li>
60<b>New header files:</b>
61The NTL header files include the new <tt>C++</tt> 
62header files <tt>&lt;cstdlib&gt;</tt>,
63<tt>&lt;cmath&gt;</tt>, and <tt>&lt;iostream&gt;</tt>.
64These new header files are essentially the same as the traditional ones,
65except that all the the names are declared in a namespace called
66<tt>std</tt>.
67
68<p>
69<li>
70<b>Nothrow new:</b>
71The NTL implementation files use the <tt>nothrow</tt> version of <tt>new</tt>.
72</ol>
73
74
75
76<p>
77If your complier is not up to date, but you want some of the benefits
78of Standard <tt>C++</tt>, you can set the <i>partial standard</i>
79flags to get any subset of the above three changes:
80<p>
81<ol>
82<li>
83<tt>NTL_PSTD_NNS</tt>: NTL namespace
84<li>
85<tt>NTL_PSTD_NHF</tt>: New header files
86<li>
87<tt>NTL_PSTD_NTN</tt>: Nothrow new
88</ol>
89
90You can set these flags either by using the configuration script
91(only on Unix-like systems), or by editing the <tt>config.h</tt> file.
92For example, to just wrap NTL in a namepsace, just pass
93<tt>NTL_PSTD_NNS=on</tt>
94as an argument to the configuration script
95when installing NTL.
96However, make sure you also turn off the <tt>NTL_STD_CXX</tt> flag;
97otherwise, these have no effect.
98
99<p>
100
101Especially when combining NTL with other libraries, the
102<tt>NTL_PSTD_NNS</tt> flag may be particularly useful
103in avoiding name clashes, even if your compiler has just a
104rudimentary implementation of namespaces.
105
106<p>
107NTL will remain usable in Traditional mode indefinitely,
108assuming compilers maintain reasonable backward compatibilty with
109pre-standard <tt>C++</tt> conventions for header files;
110however, if you want to <i>program for the future</i>, it is recommended
111to use ISO mode.
112The partial ISO modes are not highly recommended;
113they are mainly intended as a stop-gap measure
114while we wait for decent standard-conforming <tt>C++</tt>
115compilers to become available.
116
117
118<p>
119<h3>
120A crash course on namespaces
121</h3>
122
123<p>
124As already mentioned, the main difference between Traditional and ISO
125mode is that in ISO mode, all names are wrapped in namespaces.
126Namespaces are a feature that was introduced in the new <tt>C++</tt> standard.
127One can declare names (functions, types, etc.) inside a namespace.
128By default,
129such names are not visible outside the namespace without explicit
130qualification.
131
132<p>
133The main advantage of namespaces is that it solves the <i>namespace pollution
134problem</i>:
135if two libraries define the same name in two inconsistent ways,
136it is very difficult, if not impossible,
137to combine these two libraries in the same
138program.
139
140<p>
141The traditional way of avoiding such problems in languages like
142<tt>C</tt> is for a library designer to attach a prefix specific
143to that library to all names.
144This works, but makes for ugly code.
145The function overloading mechanism in <tt>C++</tt> eases the problem a bit,
146but is still not a complete solution.
147
148<p>
149
150The new
151namespace feature in <tt>C++</tt>
152provides a reasonably complete and elegant solution to the namespace
153pollution problem.
154It is one of the nicest and most important recent additions to the <tt>C++</tt>
155language.
156
157<p>
158
159Here is a simple example to illustrate namespaces.
160<p>
161<pre>
162
163namespace N {
164   void f(int);
165   void g(int);
166   int x;
167}
168
169int x;
170
171void h()
172{
173   x = 1;    // the global x
174   N::x = 0; // the x in namespace N
175   N::f(0);  // the f in namespace N
176   g(1);     // error -- g is not visible here
177}
178
179</pre>
180
181<p>
182All of this explicit qualification business
183can be a bit tedious.
184The easiest way to avoid this tedium is to use what is called
185a <i>using directive</i>, which effectively makes
186all names declared within a namespace visible in the
187global scope.
188
189Here is a variation on the previous example, with a using directive.
190
191<p>
192<pre>
193
194namespace N {
195   void f(int);
196   void g(int);
197   int x;
198}
199
200int x;
201
202using namespace N;
203
204void h()
205{
206   x = 1;    // error -- ambiguous: the global x or the x in namespace N?
207   ::x = 1;  // the global x
208   N::x = 0; // the x in namespace N
209   N::f(0);  // the f in namespace N
210   f(0);     // OK -- N::f(int) is visible here
211   g(1);     // OK -- N::g(int) is visible here
212}
213
214</pre>
215
216<p>
217Here is another example.
218
219<p>
220<pre>
221
222namespace N1 {
223   int x;
224   void f(int);
225   void g(int);
226}
227
228namespace N2 {
229   int x;
230   int y;
231   void f(double);
232   void g(int);
233}
234
235using namespace N1;
236using namespace N2;
237
238void h()
239{
240   x = 1;     // error -- ambiguous: N1::x or N2::x?
241   N1::x = 1; // OK
242   N2::x = 1; // OK
243   y = 1;     // OK  -- this is N2::y
244   g(0);      // error -- ambiguous: N1::g(int) or N2::g(int)?
245   f(0);      // OK -- N1::f(int), because it is the "best" match
246   f(0.0);    // OK  -- N2::f(double), because it is the "best" match
247}
248
249</pre>
250
251<p>
252This example illustrates the interaction between using declarations
253and function overloading resolution.
254If several overloaded versions of a function are visible,
255it is not necessarily ambiguous: the usual overload resolution
256procedure is applied, and if there is a unique "best" match,
257then there is no ambiguity.
258
259<p>
260
261The examples presented here do not illustrate all of the
262features and nuances of namespaces.
263For this, you are referred to a <tt>C++</tt> book.
264
265<p>
266<h3>
267Namespaces and NTL
268</h3>
269
270<p>
271In ISO mode, the standard library is "wrapped" in namespace <tt>std</tt>,
272and NTL is "wrapped" in namespace <tt>NTL</tt>.
273Thus, the header file <tt>&lt;NTL/ZZ.h&gt;</tt> in ISO mode looks
274something like this:
275<pre>
276
277namespace NTL {
278
279   // ...
280
281   class ZZ { /* ... */ };
282
283   // ...
284
285   ZZ operator+(const ZZ&amp; a, const ZZ&amp; b);
286   ZZ operator*(const ZZ&amp; a, const ZZ&amp; b);
287
288   std::istream&amp; operator>>(std::istream&amp; s, ZZ&amp; x);
289   std::ostream&amp; operator<<(std::ostream&amp; s, const ZZ&amp; a);
290
291   // ...
292
293 
294}
295
296</pre>
297
298Therefore, one must explicitly qualify all names, or use appropriate
299using directives.
300Here is how one could write the <a href="tour-ex1.html">first example</a> 
301of the tour in
302ISO mode.
303
304<pre>
305
306#include &lt;NTL/ZZ.h&gt;
307
308int main()
309{
310   NTL::ZZ a, b, c;
311
312   std::cin &gt;&gt; a;
313   std::cin &gt;&gt; b;
314   c = (a+1)*(b+1);
315   std::cout &lt;&lt; c &lt;&lt; "\n";
316}
317
318</pre>
319
320<p>
321Notice how everything is explicitly qualified.
322Actually, the input/output operators <tt>&lt;&lt;</tt> and <tt>&gt;&gt;</tt>,
323and the arithmetic operators <tt>+</tt> and <tt>*</tt> are not explicitly
324qualified, but rather, the compiler finds them through a gimmick
325called <i>Koenig Lookup</i>, which will look for functions (and operators)
326declared in namespace <tt>NTL</tt>, because the type of the argument
327(<tt>ZZ</tt>) is a class declared in that namespace.
328
329<p>
330
331Even with Koenig Lookup, explicit qualification can
332be a bit tedious.
333Here is the same example, this time with using directives.
334
335<pre>
336
337#include &lt;NTL/ZZ.h&gt;
338
339using namespace NTL;
340using namespace std;
341
342int main()
343{
344   ZZ a, b, c;
345
346   cin &gt;&gt; a;
347   cin &gt;&gt; b;
348   c = (a+1)*(b+1);
349   cout &lt;&lt; c &lt;&lt; "\n";
350}
351
352</pre>
353
354To write NTL client code that will compile smoothly in either
355Traditional or ISO mode, one simply does the following:
356
357<pre>
358
359#include &lt;NTL/ZZ.h&gt;
360
361NTL_CLIENT
362
363int main()
364{
365   ZZ a, b, c;
366
367   cin &gt;&gt; a;
368   cin &gt;&gt; b;
369   c = (a+1)*(b+1);
370   cout &lt;&lt; c &lt;&lt; "\n";
371}
372
373</pre>
374
375<p>
376Here, <tt>NTL_CLIENT</tt> is a macro defined by NTL
377that expands into zero, one, or two appropriate <i>using</i> directives,
378depending on the settings of <tt>NTL_STD_CXX</tt>,
379<tt>NTL_PSTD_NNS</tt>, and <tt>NTL_PSTD_NHF</tt>.
380Alternatively, instead of using the <tt>NTL_CLIENT</tt> macro,
381you can write:
382<p>
383
384<pre>
385#if (defined(NTL_PSTD_NNS) || defined(NTL_STD_CXX))
386   using namespace NTL;
387#endif
388
389#if (defined(NTL_PSTD_NHF) || defined(NTL_STD_CXX))
390   using namespace std;
391#endif
392</pre>
393
394Typically,
395when writing a program that uses NTL,
396you can
397simply insert the <tt>NTL_CLIENT</tt> as above,
398and forget about all this namespace nonsense.
399However, if you are combining libraries, you may have to disambiguate
400things from time to time.
401
402<p>
403
404The Standard <tt>C++</tt> library is huge.
405If you just use <tt>&lt;iostream&gt;</tt>, you should not
406have any ambiguous names.
407However, there are some potential ambiguities in the STL
408(Standard Template Library) part of the library.
409One that I know of is the template class <tt>negate</tt>
410defined in <tt>&lt;functional&gt;</tt>, which conflicts with the
411NTL function <tt>negate</tt>.
412With namespaces, there should be no problem, unless the client
413code explicitly uses <tt>negate</tt>, in which case you will
414have to explicitly qualify <tt>negate</tt> to tell the compiler
415which <tt>negate</tt> you mean, either <tt>std::negate</tt>
416or <tt>NTL::negate</tt>.
417
418<p>
419NTL also explicitly defines various versions of <tt>min</tt>
420and <tt>max</tt> functions.
421Template versions of these functions are also defined in the
422standard library component <tt>&lt;algorithm&gt;</tt>.
423Because of the way the function overload resolution mechanism works,
424the "right" version of <tt>min</tt> or <tt>max</tt> should always
425be chosen, without any need for explicit qualification.
426
427<p>
428There may be other possible ambiguities between the standard library
429and NTL, but if they arise, they are easily fixed through
430explicit qualification.
431
432<p>
433<h3>
434Some global names
435</h3>
436<p>
437
438It is not quite true that <i>all</i> names
439declared in NTL header files are wrapped in namespace NTL.
440There are two classes of exceptions:
441<p>
442<ul>
443<li>
444All names that start with the prefix "<tt>NTL_</tt>"
445are in fact <i>macros</i>
446There are a number of documented and undocumented
447such macros.
448Note that any name with this prefix is a macro and all macros
449start with this prefix.
450
451<p>
452
453<li>
454There are also a number of undocumented names that start with the
455prefix "<tt>_ntl_</tt>".
456These are not macros, but rather are names of functions, types, etc.,
457that are declared in the global namespace.
458Any name with this prefix is in the global namespace,
459and all names in the global namespace start with this prefix.
460All functions with <tt>"C"</tt> linkage have this prefix.
461</ul>
462<p>
463Thus, NTL "owns" all names starting with "<tt>NTL_</tt>" or "<tt>_ntl_</tt>";
464users of NTL should avoid names with these prefixes.
465
466<p>
467<h3>
468Further technicalities
469</h3>
470<p>
471
472Another thing to be aware of is that there are some small, annoying
473differences between the old standard <tt>C</tt> include files
474<tt>&lt;stdlib.h&gt;</tt> and <tt>&lt;math.h&gt;</tt>,
475and the new <tt>C++</tt> include files
476<tt>&lt;cstdlib&gt;</tt> and <tt>&lt;cmath&gt;</tt>,
477above and beyond the namespace wrapping.
478Specifically, the new header files declare several overloaded versions
479of some functions.
480For example, in the old header files, there was one function
481<pre>
482   int abs(int);
483</pre>
484Now there are several, including:
485<pre>
486   int abs(int);
487   long abs(long);
488   float abs(float);
489   double abs(double);
490   long double abs(long double);
491</pre>
492Also, functions like <tt>log</tt> and <tt>sqrt</tt> are also overloaded.
493So instead of just
494<pre>
495   double log(double);
496</pre>
497there are
498<pre>
499   float log(float);
500   double log(double);
501   long double log(long double);
502</pre>
503
504<p>
505This can lead to compile-time errors in some old codes, such as:
506<pre>
507   double log_2 = log(2);
508</pre>
509
510<p>
511With the old header files, the <tt>int</tt> value 2 would have
512been converted to a <tt>double</tt>, and the function
513<pre>
514   double log(double);
515</pre>
516would have been called.
517<p>
518With the new header files, the compiler would raise an error,
519because the function call is now ambiguous.
520<p>
521Of course, the fix is trivial:
522<pre>
523   double log_2 = log(2.0);
524</pre>
525This will compile correctly with either old or new header files.
526
527<p>
528Don't you just love the ISO?
529
530
531<p>
532<h3>
533A note on documentation
534</h3>
535<p>
536
537The "<tt>.txt</tt>" files documenting NTL's modules
538still reflect NTL's  Traditional mode.
539There should be no confusion in interpretting the meaning in ISO mode.
540Just remember: all of NTL is wrapped in namespace <tt>NTL</tt>,
541and the standard library is wrapped in namespace <tt>std</tt>.
542
543
544<p>
545<h3>
546Further changes in NTL version 4.1
547</h3>
548<p>
549
550The ISO Standard for <tt>C++</tt> is not compatible with the
551language defined in the second edition of Stroustrup's <tt>C++</tt> book.
552This is in fact quite annoying.
553Besides introducing namespaces, several modifications were made
554in version 4.1 that will allow NTL to be compiled smoothly under
555<i>either</i> the old or the new definition of the language
556(or any reasonable approximation thereof).
557These changes do not affect the (documented) NTL interface,
558and so version 4.1 should be backward compatible.
559<p>
560Here is a summary of the other changes:
561<ul>
562<li>
563Got rid of all <tt>friend</tt> functions.
564It turns out that new <tt>C++</tt> and old <tt>C++</tt> disagree
565quite strongly about the semantics of a <tt>friend</tt> function
566declaration.
567In getting rid of these, I also made a number of fields public
568which used to be private, but to prevent accidental misuse,
569I gave them strange names (e.g., the previously
570private member <tt>rep</tt> in class <tt>ZZ_p</tt>
571is now the public member <tt>_ZZ_p__rep</tt>).
572
573<p>
574This change is effective in both Traditional and ISO modes.
575
576<p>
577In my view, the ISO committee really committed an act of sabotage here.
578Now the <tt>friend</tt> mechanism is much more awkward than before,
579which makes the use of private members more awkward,
580which simply encourages programmers (like me) to avoid them altogether.
581
582<p>
583
584<li>
585When <tt>NTL_STD_CXX</tt> or <tt>NTL_PSTD_NTN</tt> are set,
586all calls to <tt>new</tt>
587have been replaced by <tt>new(std::nothrow)</tt>.
588
589<p>
590The ISO committee also committed an act of sabotage when they changed
591the semantics of the memory allocation operator <tt>new</tt>.
592In old <tt>C++</tt>, a memory allocation error simply returned
593a null pointer; in new <tt>C++</tt> an exception is thrown.
594The old semantics are available via  <tt>new(std::nothrow)</tt>.
595
596<p>
597You may of course use NTL in Traditional mode with a compiler that
598implements the new semantics for <tt>new</tt>.
599In this case, if the memory allocation fails, an exception will
600be thrown, and assuming you don't catch it, you will simply get an
601error message that is less informative than the one NTL would
602have printed.
603Also, your compiler may have a backward compatatibilty flag to
604use the old <tt>new</tt> semantics.
605
606<p>
607
608<li>
609Various and sundry other small changes, such as fixing
610occurrences of the
611the "<tt>log(2)</tt>" problem mentioned above.
612
613</ul>
614
615<p>
616
617
618<p>
619<h3>
620Standard C++ and the Real World
621</h3>
622
623<p>
624Compilers still vary in their ability to correctly implement
625Standard C++ in all its glory.
626
627<p>
628NTL  compiles correctly in in either Traditional or ISO
629mode using recent versions (2.95 and later)
630 of the <i>GNU</i> compiler (which is free).
631
632
633<p>
634It has also been reported that
635NTL compiles correctly in ISO mode using the
636Metroworks CodeWarrior Pro 5, v. 5.3 compiler on a PowerMac 7500 running
637on a 200MHz 604e.
638
639<p>
640NTL cannot be used with Microsoft Visual C++ versions 5 or 6
641in ISO mode, although this compiler still works with NTL in Traditional mode.
642I have tested NTL with  Microsoft Visual C++ version 6,
643and found that one can use the <tt>NTL_PSTD_NNS</tt> to useful effect,
644especially if one wants to use the STL.
645So one can wrap NTL in a namespace.
646However, the <tt>NTL_PSTD_NHF</tt> still does not work:
647MSVC++ 6 is very inconsistent about the location of a number of
648names; even when one uses the new header files, some names
649in the standard library are in namespace <tt>std</tt>,
650while others are in the global namespace.
651Further, it appears that Koenig lookup is not properly
652implemented in MSVC++ 6, but luckily, NTL does not rely on this.
653
654<p>
655It appears that some later versions of Microsoft C++ are much
656more standards compliant, and may in fact work with NTL in ISO mode.
657
658
659<p>
660As usual,
661NTL should continue to work in Traditional mode on just about any
662available <tt>C++</tt> compiler.
663
664<p>
665
666
667
668
669<center>
670<a href="tour-modules.html"><img src="arrow1.gif" alt="[Previous]" align=bottom></a>
671 <a href="tour.html"><img src="arrow2.gif" alt="[Up]" align=bottom></a> 
672<a href="tour-unix.html"> <img src="arrow3.gif" alt="[Next]" align=bottom></a>
673</center>
674</body>
675</html>
Note: See TracBrowser for help on using the repository browser.