I am currently going through the 5th edition of C++ Primer by Lahoie, Lippman and Moo and have been struggling with a few things.
Firstly, I just wanted to confirm, when using any of the cctype functions, I have to make sure I include the header, right? Because, initially, I forgot to include it and yet it still ran. That's really confused me.
Also, I was browsing for a different problem (which I'll get to) and found another issue haha! When using anything from cctype, are I supposed to write it as std::/write using std::, e.g. if I use the tolower either write std::tolower at every instance/write a using statement for it. This would make sense as it did say that they are "defined in the std namespace" but I didn't realise and have been writing it without and haven't had an issue. And I'm guessing similar for size_t, right?
Speaking of size_t, I have an issue. This is my code:
// Exercise Section 3.5.2., Exercise 3.30
#include <iostream>
#include <cstddef>
using std::cout; using std::endl;
int main()
{
constexpr size_t num_size = 10;
int num[num_size] = {};
for (size_t n = 0; n < num_size; ++n) {
num[n] = n;
cout << num[n] << endl;
}
return 0;
}
So the code is supposed define an array of 10 ints and give each element the same value as its position in the array.
It runs correctly, but I am receiving an error at the num[n]=n part. It says Implicit conversion loses integer precision: size_t (aka 'unsigned long') to int.
I understand what this means, but my issue is that the book says "when we use a variable to subscript an array, we normally should define that variable to type size_t". I have done this and it gives this error. It does run fine but it seems like that sort of thing that can lead to errors.
P.S. In this code, like I asked above, should I have using std::size_t?
Must I include the header even though it works without?
Yes, you must always include at least one header providing each definition / declaration you need, unless the exact prototype / type definition is guaranteed and you put it directly into your source code.
Some standard headers may include others, which might let you get away with being sloppy some of the time, but you will rue it the day you upgrade / port to a different implementation.
I read all the declarations and definitions are "defined in the std namespace" but I didn't realise and have been writing it without and haven't had an issue. And I'm guessing similar for size_t, right?
Yes, it's the same. Due to compatibility, it is possible for the <c...> headers adopted by inclusion from C / Unicode to also provide their symbols in the global namespace.
17.6.1.2 Headers [headers]
1 Each element of the C++ standard library is declared or defined (as appropriate) in a header.175
2 The C++ standard library provides 55 C++ library headers, as shown in Table 14.
3 The facilities of the C standard Library are provided in 26 additional headers, as shown in Table 15.
4 Except as noted in Clauses 18 through 30 and Annex D, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in the C standard library (1.2) or the C Unicode TR, as appropriate, as if by inclusion. In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).
5 Names which are defined as macros in C shall be defined as macros in the C++ standard library, even if C grants license for implementation as functions. [ Note: The names defined as macros in C include the following: assert, offsetof, setjmp, va_arg, va_end, and va_start. —end note ]
6 Names that are defined as functions in C shall be defined as functions in the C++ standard library.176
7 Identifiers that are keywords or operators in C++ shall not be defined as macros in C++ standard library headers.177
8 D.5, C standard library headers, describes the effects of using the name.h (C header) form in a C++ program. 178
In my example program I used size_t for the array index. That works, though I get a warning. Should I have done so, and could it in general lead to errors?
Well, naturally the same about namespace std applies, as you guessed.
As to the rest, there's a wonderful phrase: "Good advice comes with a rationale".
The reason you should use std::size_t for indices is that this type a) signals to readers that it's a size or index and b) it is guaranteed to be big enough.
In your case, a lowly int, with its guaranteed minimum maximum of 215-1 would have been perfectly fine.
An alternative is just casting to the proper type on assignment.
You asked:
Firstly, I just wanted to confirm, when using any of the cctype functions, I have to make sure I include the header, right?
Yes, that is right. You might get some function declarations or other declarations indirectly but that is not portable code. You should understand where the standard says a declaration is available and include that header file before using a function, a type, etc.
You asked:
And I'm guessing similar for size_t, right?
Yes, you should use std::size_t.
There is an SO post related to the topic. Browse Difference between size_t and std::size_t.
You asked:
In this code, like I asked above, should I have using std::size_t?
In the loop, it's OK to use int too. The suggestion to use std::size_t for indexing an array is a good suggestion but is not inviolable.
If you choose to use size_t for n, it's OK to use static_cast to convert it to an int to get rid of the compiler warning/error.
num[n] = static_cast<int>(n);
You declare your array as
int num[num_size] = {};
This means it is an array of int that has 10 elements.
Then you say
for (size_t n = 0; n < num_size; ++n)
num[n] = n;
Note that n is of type size_t aka unsigned long. Therefore you are putting unsigned long values into your int array, so they are being implicitly converted to int values.
The standard headers put a bunch of stuff in the global namespace. Ideally they wouldn't, but they do. Usually that's because something is really a macro rather than a typedef or function.
You can sometimes get away without including headers because some other header that you have included includes the missing one.
I have to make sure I include the header, right? Because, initially, I
forgot to include it and yet it still ran.
Some standard headers can include other headers. However it is a good idea to include a header explicitly if some declarations from the header are used in the program. It may occur such a way that in other implementations of the included headers the required header will not be included and the compiler will issue an error.
. This would make sense as it did say that they are "defined in the
std namespace" but I didn't realise and have been writing it without
and haven't had an issue.
The C++ Standard allows compilers to place C standard functions in the global namespace. Though even in this case it is better to specify explicitly namespace std where the function will be declared in any case.
As for the last question then the elements of the array have type int while you assign to them values of type size_t The problem is that type int can not accomodate all values of type size_t and the compiler warns you about this. You could explicitly specify casting that to say the compiler that you know what you are doing.
num[n] = ( int )n;
or
num[n] = static_cast<int>( n );
Related
I'm learning C++ with the book C++ Primer, and it says that "size_t" is defined in "cstddef" header, but in this exercise:
#include <iostream>
using namespace std;
int main()
{
int ar[10];
for (size_t x = 0; x < 10; ++x)
ar[x] = x;
for (auto a : ar)
cout << ar[a] << " ";
cout << endl;
return 0;
}
That doesn't have included the header, Visual Studio 2017 (and c++ shell) compiles the program without error.
size_t is really a grey area. std::size_t is the result type of sizeof, but sizeof is a built-in operator you can use without any #include at all. Consider this complete little program:
// no includes, no using namespace std
int main()
{
auto x = sizeof(int); // x is std::size_t
}
On top of that, Visual C++ has always behaved a bit strangely here. Even with settings like /permissive- /std:c++latest in the newest version of the compiler, it still allows the following illegal code:
// no includes, no using namespace std
int main()
{
size_t i = 0;
}
In fact, it would even allow this:
// no includes, no using namespace std
int main()
{
int ar[10];
for (size_t x = 0; x < 10; ++x)
ar[x] = x;
for (auto a : ar)
;
return 0;
}
Nevertheless, what others said about the indirect inclusion of headers is correct. To be precise, the C++ standard says the following about standard-library headers at §20.5.5.2:
A C++ header may include other C++ headers.
Which means that Visual C++ behaves correctly in your case anyway. Once you include <iostream>, the implementation is free to indirectly include one of the six standard C++ headers that define std::size_t, and your using namespace std; (which is evil) does the rest.
The C++ standard even guarantees some of such indirect inclusions, but this isn't one of them, so in order to make your code compatible with other compilers, you are strongly encouraged to include <cstddef> or one of the others that guarantee std::size_t.
Standard headers are allowed to include other standard headers. Since headers in different implementations have different dependencies, you should still try to explicitly include everything that you need. It's possible that your program wouldn't build on Linux's libstdc++ or macOS's libc++, for instance.
Standard header will usually include other standard headers, so in many cases you might get away with not including proper ones.
The problem is that such relations between headers are not in the standard e.g. depend on implementatation. If you don't include required headers, your code might work on one compiler, but might fail on another.
Usually if you know that something defined in header X uses type T in its definition, you might assume type T will be available after including X. For example <vector> uses std::size_t as part of std::vector definition, so it will usually include <cstddef>.
Sometimes forward declarations can be used to avoid including other standard headers. But this is only possible with classes and structures, not typedefs.
Some implementations, like GNU Libc for example, are more strict and try to avoid including standard headers internally. Others, like MSVC, are less strict. Code that works with GNU Libc will usually work with MSVC.
It is hard to verify that your code includes everything you need. There are tools that can help you find missing include's, but building your code with multiple compilers is usually the best way to find those issues.
Nope, std::size_t might be defined in multiple headers:
Defined in header <cstddef>
Defined in header <cstdio>
Defined in header <cstdlib>
Defined in header <cstring>
Defined in header <ctime>
Defined in header <cwchar>
Also note, that <iostream> itself includes other headers.
Firstly, std::size_t is defined in a number of standard headers: <cstddef>, <cstdio>, <cstdlib>, <cstring>, <ctime>, and <cwchar>.
Without #includeing one of these, your code is not required to compile.
Practically, a lot of implementations of the standard library have various standard headers #include each other, in which case your code will compile. It is pretty common, but NOT guaranteed, for at least one of the headers that defines std::size_t (or even their C header equivalents like <stddef.h>) to be included by other headers in the C++ standard library.
More specifically, a lot of parts of the standard library work use dynamic memory allocation (standard containers, stream buffers, etc). An obvious - but not required - implementation choice is that they use size_t to represent sizes. For example, standard containers like std::vector have an associated size_type, and std::vector<any_type>::size_type can be, and often is, equivalent to std::size_t.
<iostream> (along with headers it automatically #includes) is not required to include a header that defines std::size_t, but - equally - nothing in the standard disallows it.
In the end it comes down to how cautious you want to be concerning portability. If <iostream> brings in a definition of std::size_t with your particular compiler, then your code will compile. It is possible (although unlikely in practice, not impossible) that a future release of your compiler will update the standard headers to change that. If you intend to port your code to another implementation (compiler and standard library) in future, there is a greater likelihood your code will need to be modified.
Practically, there is no harm by explicitly #includeing <cstddef> or any other header that defines std::size_t. That way, your code that uses std::size_t will compile, regardless of how other standard headers vary between implementations.
According to cppreference.com size_t is defined in several headers, namely
<cstddef>
<cstdio>
<cstring>
<ctime>
And, since C++11, also in
<cstdlib>
<cwchar>
First of all, I wonder why this is the case. Isn't this in contradiction to the DRY principle?
Which one of the above headers should I include to use size_t? Does it matter at all?
Assuming I wanted to minimize the functions and types I was importing I'd go with cstddef as it doesn't declare any functions and only declares 6 types. The others focus on particular domains (strings, time, IO) that may not matter to you.
Note that cstddef only guarantees to define std::size_t, that is, defining size_t in namespace std, although it may provide this name also in the global namespace (effectively, plain size_t).
In contrast, stddef.h (which is also a header available in C) guarantees to define size_t in the global namespace, and may also provide std::size_t.
In fact the synopsis (included in the C++ standard) of several headers specifially include size_t as well as further headers define the type size_t (based on the C standard as the <cX> headers are just ISO C <X.h> headers with noted changes where removal of size_t is not indicated).
The C++ standard however, refers to <cstddef> for the definition of std::size_t
in 18.2 Types,
in 5.3.3 Sizeof,
in 3.7.4.2 Deallocation functions (which refers to 18.2) and
in 3.7.4.1 Allocation functions (also refers to 18.2).
Therefore and because of the fact that <cstddef> only introduces types and no functions, I'd stick to this header to make std::size_t available.
Note a few things :
The type of std::size_t is obtainable using decltype without including a header
If you're planning to introduce a typedef in your code anyway (i.e. because you write a container and want to provide a size_type typedef) you can use the global sizeof, sizeof... or alignof operators to define your type without including any headers at all since theose operators return std::size_t per standard definition and you can use decltype on them:
using size_type = decltype(alignof(char));
std::size_t is not per se globally visible although functions with std::size_t arguments are.
The implicitly declared global allocation and deallocation functions
void* operator new(std::size_t);
void* operator new[](std::size_t);
void operator delete(void*);
void operator delete[](void*);
do NOT introduce size_t, std or std::size_t and
referring to std or std::size_t is ill-formed unless the name has been declared by including the appropriate header.
The user may not redefine std::size_t although it is possible to have multiple typedefs referring to the same type in the same namespace.
Although, the occurrence of multiple definitions of size_t within std is perfectly valid as per 7.1.3 / 3, it is not allowed to add any declarations to namespace std as per 17.6.4.2.1 / 1:
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified.
Adding a proper typedef for size_t to the namespace does not violate 7.1.3 but it does violate 17.6.4.2.1 and leads to undefined behaviour.
Clarification: Try not to misinterpret 7.1.3 and do not add declarations or definitions to std (except a few template specialization cases where a typedef is not a template specialization). Extending the namespace std
All standard library header files have the same definition; it does not matter which one you include in your own code. On my computer, I have the following declaration in _stddef.h. This file is included by every file you listed.
/*
Define the size_t type in the std namespace if in C++ or globally if in C.
If we're in C++, make the _SIZE_T macro expand to std::size_t
*/
#if !defined(_SIZE_T) && !defined(_SIZE_T_DEFINED)
# define _SIZE_T_DEFINED
#if defined(_WIN64)
typedef unsigned __int64 size_t;
#else
typedef unsigned int size_t;
#endif
# if defined(__cplusplus)
# define _SIZE_T std::size_t
# else
# define _SIZE_T size_t
# endif
#endif
You could do without a header:
using size_t = decltype(sizeof(int));
using size_t = decltype(sizeof 1); // The shortest is my favourite.
using size_t = decltype(sizeof "anything");
This is because the C++ standard requires:
The result of sizeof and sizeof... is a constant of type std::size_t. [ Note: std::size_t is defined in the standard header <cstddef> (18.2). — end note ]
In other words, the standard requires:
static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value,
"This never fails.");
Also note, that it is perfectly fine to make this typedef declaration in the global and in std namespace, as long as it matches all other typedef declarations of the same typedef-name (a compiler error is issued on non-matching declarations).
This is because:
§7.1.3.1 A typedef-name does not introduce a new type the way a class declaration (9.1) or enum declaration does.
§7.1.3.3 In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.
To sceptics saying that this constitutes an addition of a new type into namespace std, and such an act is explicitly prohibited by the standard, and this is UB and that is all there to it; I have to say that this attitude amounts to ignoring and denying deeper understanding of the underlying issues.
The standard bans adding new declarations and definitions into namespace std because by doing so the user may make a mess of the standard library and shoot his entire leg off. For the standard writers it was easier to let the user specialize a few specific things and ban doing anything else for good measure, rather than ban every single thing which the user should not do and risk missing something important (and that leg). They did it in the past when requiring that no standard container shall be instantiated with an incomplete type, while in fact some containers could well do (see The Standard Librarian: Containers of Incomplete Types by Matthew H. Austern):
... In the end, it all seemed too murky and too poorly understood; the standardization committee didn't think there was any choice except to say that STL containers aren't supposed to work with incomplete types. For good measure, we applied that prohibition to the rest of the standard library too.
... In retrospect, now that the technology is better understood, that decision still seems basically right. Yes, in some cases it's possible to implement some of the standard containers so that they can be instantiated with incomplete types — but it's also clear that in other cases it would be difficult or impossible. It was mostly chance that the first test we tried, using std::vector, happened to be one of the easy cases.
Given that the language rules require std::size_t to be exactly decltype(sizeof(int)), doing namespace std { using size_t = decltype(sizeof(int)); } is one of those things that do not break anything.
Prior to C++11 there was no decltype and thus no way to declare the type of sizeof result in one simple statement without getting a good deal of templates involved. size_t aliases different types on different target architectures, however, it would not be an elegant solution to add a new built-in type just for the result of sizeof, and there are no standard built-in typedefs. Hence, the most portable solution at the time was to put size_t type alias in some specific header and document that.
In C++11 there is now a way to write down that exact requirement of the standard as one simple declaration.
Is there any technical reason for standard library (C or C++) implementations to, IMO abuse, underscores the way they do (=prefix everything with two undescore + add a trailing underscore to denote that a variable is a member variable)?
I get that /.*__.*/ and /_[A-Z].*/ (<= regexes) are reserved-by-implementation. But isn't that supposed to refer to the implementation of the compiler rather than a (standard) library?
Couldn't a standard library behave like any other library in terms of choosing its internal names?
There is a good reason for the standard library to start internal names with two underscores: Such names are reserved for the implementation.
Imagine you write the following code:
#include <iostream>
using namespace std;
long square(long x)
{
return x*x;
}
int main()
{
cout << square(3) << endl;
}
I guess you would not be happy if this ended up calling some internal function square(int) used in implementing the standard library and doing something completely different, because it's a better match than your square(long) for square(3).
By prefixing all internal names with double underscores and at the same time the standard declaring that you are not allowed to do the same, the standard library authors ensure that something like this cannot happen.
Now you may say that <iostream> is not part of the STL, but every standard library header may include any other standard library header, so iostream may well include an STL header for use in its implementation.
Another reason why identifiers with double underscores make sense even in the case of local identifiers that are not seen externally is that you might have defined a macro of the same name. Consider:
#define value 15
#include <iostream>
int main()
{
std::cout << value;
}
This is legal code and certainly should output 15. But now imagine what happened if some object in iostream declared a local variable names value. Your code obviously wouldn't compile.
Note that the standard library is part of the implementation (it's described in the C++ standard, after all), so it can use reserved names however it likes.
So this is something that I've always wondered but was never quite sure about. So it is strictly a matter of curiosity, not a real problem.
As far as I understand, whenyou do something like #include <cstdlib> everything (except macros of course) are declared in the std:: namespace. Every implementation that I've ever seen does this by doing something like the following:
#include <stdlib.h>
namespace std {
using ::abort;
// etc....
}
Which of course has the effect of things being in both the global namespace and std. Is this behavior guaranteed? Or is it possible that an implementation could put these things in std but not in the global namespace? The only way I can think of to do that would be to have your libstdc++ implement every c function itself placing them in std directly instead of just including the existing libc headers (because there is no mechanism to remove something from a namespace). Which is of course a lot of effort with little to no benefit.
The essence of my question is, is the following program strictly conforming and guaranteed to work?
#include <cstdio>
int main() {
::printf("hello world\n");
}
EDIT: The closest I've found is this (17.4.1.2p4):
Except as noted in clauses 18 through
27, the contents of each header cname
shall be the same as that of the
corresponding header name.h, as
specified in ISO/IEC 9899:1990
Programming Languages C (Clause 7), or
ISO/IEC:1990 Programming Languages—C
AMENDMENT 1: C Integrity, (Clause 7),
as appropriate, as if by inclusion. In
the C + + Standard Library, however,
the declarations and definitions
(except for names which are defined as
macros in C) are within namespace
scope (3.3.5) of the namespace std.
which to be honest I could interpret either way. "the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in ISO/IEC 9899:1990 Programming Languages C" tells me that they may be required in the global namespace, but "In the C + + Standard Library, however, the declarations and definitions (except for names
which are defined as macros in C) are within namespace scope (3.3.5) of the namespace std." says they are in std (but doesn't specify any other scoped they are in).
Here's a nice synopsis of the situation (with some reality vs. what the standard says) from Stephan T. Lavavej of the MSVC team (http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx#8904359):
> also, <cstddef>, <cstdlib>, and std::size_t etc should be used!
I used to be very careful about that. C++98 had a splendid dream wherein <cfoo> would declare everything within namespace std, and <foo.h> would include <cfoo> and then drag everything into the global namespace with using-declarations. (This is D.5 [depr.c.headers].)
This was ignored by lots of implementers (some of which had very little control over the C Standard Library headers). So, C++0x has been changed to match reality. As of the N2723 Working Paper, http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf , now <cfoo> is guaranteed to declare everything within namespace std, and may or may not declare things within the global namespace. <foo.h> is the opposite: it is guaranteed to declare everything within the global namespace, and may or may not declare things within namespace std.
In reality and in C++0x, including <cfoo> is no safeguard against everything getting declared in the global namespace anyways. That's why I'm ceasing to bother with <cfoo>.
This was Library Issue 456, http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456 .
(C++0x still deprecates the <foo.h> headers from the C Standard Library, which is hilarious.)
I've never been fond of the <cfoo> headers myself, and found that I've always use <foo.h>. Now I feel like I can stop being anxious about my lack of C++ 'purity' in that regard.
At the present time, no. In fact, even though the code will work with every compiler I now of, it's really not supposed to work at all -- #includeing one of the c* headers is only supposed to give you access to the names inside of namespace std.
Since implementation of this was such a pain (getting it right essentially required duplicating the entire C library as a C++ library in the right namespace), in C++ 0x they've changed the requirements a bit -- your code is now allowed to work, though (at least if memory serves) it's still not required to work.
I cannot speak for the standards, as I have not read them, but one could envision a C++ environment that is not built on top of a C environment, or where the C environment is a compatibility layer on top of underlying C++ APIs. In such a case, these guarantees may not be made. I would be surprised if such an implementation would be prohibited from being a compliant implementation.
The C++ Programming Language : Special Edition states on page 431 that...
For every header < X.h > defining part of the C standard library in the global namespace and also in namespace std, there is a header < cX > defining the same names in the std namespace only.
However, when I use C headers in the < cX > style, I don't need to qualify the namespace. For example...
#include <cmath>
void f() {
double var = sqrt( 17 );
}
This would compile fine. Even though the book says that using the < cX > header defines names in the std namespace only, you are allowed to use those names without qualifying the namespace. What am I missing here?
P.S. Using the GNU.GCC compiler
Stephan T. Lavavej, a member of the MSVC team, addresses the reality of this situation (and some of the refinements to the standard) in this comment on one of his blog postings (http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx#8904359):
> also, <cstddef>, <cstdlib>, and std::size_t etc should be used!
I used to be very careful about that. C++98 had a splendid dream wherein <cfoo> would declare everything within namespace std, and <foo.h> would include <cfoo> and then drag everything into the global namespace with using-declarations. (This is D.5 [depr.c.headers].)
This was ignored by lots of implementers (some of which had very little control over the C Standard Library headers). So, C++0x has been changed to match reality. As of the N2723 Working Paper, http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf , now <cfoo> is guaranteed to declare everything within namespace std, and may or may not declare things within the global namespace. <foo.h> is the opposite: it is guaranteed to declare everything within the global namespace, and may or may not declare things within namespace std.
In reality and in C++0x, including <cfoo> is no safeguard against everything getting declared in the global namespace anyways. That's why I'm ceasing to bother with <cfoo>.
This was Library Issue 456, http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456 .
(C++0x still deprecates the <foo.h> headers from the C Standard Library, which is hilarious.)
I'm in 100% agreement with Lavavej, except I never tried to be very careful about using the <cfoo> style headers even when I first started using C++ - the standard C ones were just too ingrained - and there was never any real world problem using them (and apparently there was never any real world benefit to using the <cfoo> style headers).
The rule for the C libraries differs from C++ libraries for namespaces
gcc interprets the standard in Gcc docs as
The standard specifies that if one includes the C-style header (<math.h> in this case), the symbols will be available in the global namespace and perhaps in namespace std:: (but this is no longer a firm requirement.) One the other hand, including the C++-style header (<cmath>) guarantees that the entities will be found in namespace std and perhaps in the global namespace.
In the draft C0X++ spec it says in section 17.6.2.3 Headers
It is unspecified whether these names are first declared within the global namespace scope and are then injected
into namespace std by explicit using-declarations
It's hard to fix this without implementing the C library twice. See DR 456, which basically proposes giving up on the problem.
Why do you say "This would compile fine" when it violates the Standard? Who allows you to use those names without qualifying the namespace? Have you tested this on a particular implementation and found that it works?
I strongly advise against using some particular non-standard feature because it happens to work on your compiler of choice. Such things break easily, perhaps with a later version of the same compiler.
You are probably missing using a standards-conformant compiler (or the one you use is configured to be compatible with pre-standard code).