⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tour-stdcxx.html

📁 NTL is a high-performance, portable C++ library providing data structures and algorithms for manipul
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<html>
<head>
<title>
A Tour of NTL: Traditional and ISO Modes  </title>
</head>

<body bgcolor="#fff9e6">
<center>
<a href="tour-modules.html"><img src="arrow1.gif" alt="[Previous]" align=bottom></a>
 <a href="tour.html"><img src="arrow2.gif" alt="[Up]" align=bottom></a> 
<a href="tour-unix.html"> <img src="arrow3.gif" alt="[Next]" align=bottom></a>
</center>

<h1> 
<p align=center>
A Tour of NTL: Traditional and ISO Modes
</p>
</h1>

<p> <hr> <p>

<p>

As of version 4.1,
NTL can be compiled and used in one of two modes: Traditional or ISO.
<i>As of NTL version 5.4, ISO mode is the default.</i>

<p>
To revert to traditional mode, you can pass <tt>NTL_STD_CXX=off</tt>
as an argument to the configuration script
when <a href="tour-unix.html">installing NTL on a Unix or Unix-like system</a>,
which will unset the flag <tt>NTL_STD_CXX</tt> in the <tt>config.h</tt>
file.
Alternatively (and especially on non-Unix systems),
you can unset this flag  by hand by editing 
the the <tt>config.h</tt> file.
<p>



<p>
In Traditional mode, the NTL header files include the traditional
<tt>C++</tt> header files <tt>&lt;stdlib.h&gt;</tt>,
<tt>&lt;math.h&gt;</tt>, and <tt>&lt;iostream.h&gt;</tt>.
These files declare a number of names (functions, types, etc.)
in the <i>global namespace</i>.
Additionally, the NTL header files declare a number of names,
also in the global namespace.

<p>
In ISO mode, three things change:

<ol>
<li>
<b>NTL namespace:</b>
The NTL header files wrap all NTL names in a namespace, called <tt>NTL</tt>.

<p>
<li>
<b>New header files:</b>
The NTL header files include the new <tt>C++</tt> 
header files <tt>&lt;cstdlib&gt;</tt>,
<tt>&lt;cmath&gt;</tt>, and <tt>&lt;iostream&gt;</tt>.
These new header files are essentially the same as the traditional ones,
except that all the the names are declared in a namespace called 
<tt>std</tt>.

<p>
<li>
<b>Nothrow new:</b>
The NTL implementation files use the <tt>nothrow</tt> version of <tt>new</tt>.
</ol>



<p>
If your complier is not up to date, but you want some of the benefits
of Standard <tt>C++</tt>, you can set the <i>partial standard</i>
flags to get any subset of the above three changes:
<p>
<ol>
<li>
<tt>NTL_PSTD_NNS</tt>: NTL namespace
<li>
<tt>NTL_PSTD_NHF</tt>: New header files
<li>
<tt>NTL_PSTD_NTN</tt>: Nothrow new
</ol>

You can set these flags either by using the configuration script
(only on Unix-like systems), or by editing the <tt>config.h</tt> file.
For example, to just wrap NTL in a namepsace, just pass 
<tt>NTL_PSTD_NNS=on</tt>
as an argument to the configuration script
when installing NTL.
However, make sure you also turn off the <tt>NTL_STD_CXX</tt> flag;
otherwise, these have no effect.

<p>

Especially when combining NTL with other libraries, the
<tt>NTL_PSTD_NNS</tt> flag may be particularly useful
in avoiding name clashes, even if your compiler has just a
rudimentary implementation of namespaces.

<p>
NTL will remain usable in Traditional mode indefinitely,
assuming compilers maintain reasonable backward compatibilty with 
pre-standard <tt>C++</tt> conventions for header files;
however, if you want to <i>program for the future</i>, it is recommended
to use ISO mode.
The partial ISO modes are not highly recommended;
they are mainly intended as a stop-gap measure 
while we wait for decent standard-conforming <tt>C++</tt>
compilers to become available.


<p>
<h3>
A crash course on namespaces
</h3>

<p>
As already mentioned, the main difference between Traditional and ISO
mode is that in ISO mode, all names are wrapped in namespaces.
Namespaces are a feature that was introduced in the new <tt>C++</tt> standard.
One can declare names (functions, types, etc.) inside a namespace.
By default,
such names are not visible outside the namespace without explicit
qualification.

<p>
The main advantage of namespaces is that it solves the <i>namespace pollution
problem</i>:
if two libraries define the same name in two inconsistent ways,
it is very difficult, if not impossible,
to combine these two libraries in the same 
program.

<p>
The traditional way of avoiding such problems in languages like
<tt>C</tt> is for a library designer to attach a prefix specific
to that library to all names.
This works, but makes for ugly code.
The function overloading mechanism in <tt>C++</tt> eases the problem a bit,
but is still not a complete solution.

<p>

The new
namespace feature in <tt>C++</tt>
provides a reasonably complete and elegant solution to the namespace
pollution problem.
It is one of the nicest and most important recent additions to the <tt>C++</tt>
language.

<p>

Here is a simple example to illustrate namespaces.
<p>
<pre>

namespace N {
   void f(int);
   void g(int);
   int x;
}

int x;

void h()
{
   x = 1;    // the global x
   N::x = 0; // the x in namespace N
   N::f(0);  // the f in namespace N
   g(1);     // error -- g is not visible here
}

</pre>

<p>
All of this explicit qualification business
can be a bit tedious.
The easiest way to avoid this tedium is to use what is called
a <i>using directive</i>, which effectively makes
all names declared within a namespace visible in the
global scope.

Here is a variation on the previous example, with a using directive.

<p>
<pre>

namespace N {
   void f(int);
   void g(int);
   int x;
}

int x;

using namespace N;

void h()
{
   x = 1;    // error -- ambiguous: the global x or the x in namespace N?
   ::x = 1;  // the global x
   N::x = 0; // the x in namespace N
   N::f(0);  // the f in namespace N
   f(0);     // OK -- N::f(int) is visible here
   g(1);     // OK -- N::g(int) is visible here
}

</pre>

<p>
Here is another example.

<p>
<pre>

namespace N1 {
   int x;
   void f(int);
   void g(int);
}

namespace N2 {
   int x;
   int y;
   void f(double);
   void g(int);
}

using namespace N1;
using namespace N2;

void h()
{
   x = 1;     // error -- ambiguous: N1::x or N2::x?
   N1::x = 1; // OK
   N2::x = 1; // OK
   y = 1;     // OK  -- this is N2::y
   g(0);      // error -- ambiguous: N1::g(int) or N2::g(int)?
   f(0);      // OK -- N1::f(int), because it is the "best" match 
   f(0.0);    // OK  -- N2::f(double), because it is the "best" match
}

</pre>

<p>
This example illustrates the interaction between using declarations
and function overloading resolution.
If several overloaded versions of a function are visible,
it is not necessarily ambiguous: the usual overload resolution
procedure is applied, and if there is a unique "best" match,
then there is no ambiguity.

<p>

The examples presented here do not illustrate all of the
features and nuances of namespaces.
For this, you are referred to a <tt>C++</tt> book.

<p>
<h3>
Namespaces and NTL
</h3>

<p>
In ISO mode, the standard library is "wrapped" in namespace <tt>std</tt>,
and NTL is "wrapped" in namespace <tt>NTL</tt>.
Thus, the header file <tt>&lt;NTL/ZZ.h&gt;</tt> in ISO mode looks
something like this:
<pre>

namespace NTL {

   // ...

   class ZZ { /* ... */ };

   // ...

   ZZ operator+(const ZZ&amp; a, const ZZ&amp; b);
   ZZ operator*(const ZZ&amp; a, const ZZ&amp; b);

   std::istream&amp; operator>>(std::istream&amp; s, ZZ&amp; x);
   std::ostream&amp; operator<<(std::ostream&amp; s, const ZZ&amp; a);

   // ...

  
}

</pre>

Therefore, one must explicitly qualify all names, or use appropriate
using directives.
Here is how one could write the <a href="tour-ex1.html">first example</a> 
of the tour in
ISO mode.

<pre>

#include &lt;NTL/ZZ.h&gt;

int main()
{
   NTL::ZZ a, b, c; 

   std::cin &gt;&gt; a; 
   std::cin &gt;&gt; b; 
   c = (a+1)*(b+1);
   std::cout &lt;&lt; c &lt;&lt; "\n";
}

</pre>

<p>
Notice how everything is explicitly qualified.
Actually, the input/output operators <tt>&lt;&lt;</tt> and <tt>&gt;&gt;</tt>,
and the arithmetic operators <tt>+</tt> and <tt>*</tt> are not explicitly
qualified, but rather, the compiler finds them through a gimmick
called <i>Koenig Lookup</i>, which will look for functions (and operators)
declared in namespace <tt>NTL</tt>, because the type of the argument
(<tt>ZZ</tt>) is a class declared in that namespace.

<p>

Even with Koenig Lookup, explicit qualification can
be a bit tedious.
Here is the same example, this time with using directives.

<pre>

#include &lt;NTL/ZZ.h&gt;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -