@Team LiB
# operator and directive Stringify operator and null directive
# // Null directive

# identifier

A preprocessor directive with no directive name is called a null directive. It has no effect.

The # operator can also be used as a unary operator, sometimes called the stringify operator because it turns its operand into a string. It can be used only in the macro replacement text of a #define directive. It must be followed by a parameter name for the macro being defined. The # operator and the parameter name are replaced by a string literal whose contents are the text of the macro argument that corresponds to the macro parameter. The macro argument is not expanded before being converted to a string. Whitespace in the argument is condensed to a single space character between tokens; leading and trailing whitespace is removed.

The evaluation order of # and ## operators is undefined. If the order is important, you can control the order by using multiple macros.

Example

The following example prints the text [now is the time]:

#define now then

#define is was

#define print(stuff)  std::cout << "[" #stuff "]\n"

print(  now   is the   time   );

See Also

## operator, #define directive
    Team LiB


## operator Concatenation operator
identifier ## identifier

The ## operator is a binary operator, sometimes called the concatenation operator because it concatenates preprocessor tokens. It can be used only in the macro replacement text of a #define directive. It must not appear at the start or end of the macro replacement text. The operands of the ## operator must be parameter names for the macro being defined. They are replaced by the corresponding macro arguments, which are not expanded. The tokens immediately adjacent to the ## operator are concatenated to form a single token. If the result is not a valid token, the behavior is undefined; otherwise, the token is expanded normally.

The evaluation order of # and ## operators is undefined. If the order is important, you can control the order by using multiple macros.

Example

The following example prints std to cout because the concat macro assembles the token std from s, t, and d:

#define s this is not expanded by the concatenation operator

#define t nor is this, so the result is the token std

#define concat(part1, part2, part3) part1 ## part2 ## part3

concat(s, t, d)::cout << "std";

See Also

# operator, #define directive


defined operator Tests whether a macro is defined
defined(identifier)

defined identifier

The unary operator defined(identifier) (also written as defined identifier, without the parentheses) evaluates to 1 if identifier is a known macro name at the point of the defined operator, or 0 if it is not known. The operator is evaluated only in the argument to an #if or #elif directive.

The behavior is undefined if the defined operator is used in any other way, or if the token defined results from macro expansion.

See Also

#define directive, #elif directive, #if directive, #ifdef directive, #ifndef directive, #undef directive


#elif directive Else-if for conditional compilation
#elif constant-expression

The #elif directive marks a region of conditional compilation. Every #elif must be paired with an introductory directive: #if, #ifdef, or #ifndef. If the initial condition was false (0), and every subsequent #elif condition is false, and constant-expression is true (nonzero), subsequent statements are compiled until the next #elif, #else, or #endif directive is reached for this level of nesting.

See Also

#else directive, #if directive


#else directive Else for conditional compilation
#else

The #else directive marks a region of conditional compilation. Every #else must be paired with an introductory directive: #if, #ifdef, or #ifndef. There can be any number of intervening #elif directives. If the initial condition was false (0), and every subsequent #elif condition is false, statements that follow the #else directive are compiled until the corresponding #endif directive is reached.

See Also

#if directive


#endif directive Ends conditional compilation
#endif

The #endif directive ends a region of conditional compilation.

See Also

#if directive


#error directive Issues an error message
#error message

The #error directive tells the preprocessor to issue an error message and mark the source file as ill-formed, just as if the programmer made a programming error that the compiler detected. You can supply any sequence of preprocessor tokens as the message, and those tokens are echoed in the error message.

Example

#if !defined(_  _cplusplus) || (_  _cplusplus < 199711L)

  #error Not a conforming C++ compiler.

#endif

See Also

#line directive


#if directive Tests a condition
#if constant-expression

The #if directive begins a region of conditional compilation, that is, a region within a source file where preprocessor directives determine whether the code in the region is compiled. A conditional region starts with #ifdef, #ifndef, or #if and ends with #endif. Each region can have any number of #elif directives and an optional #else directive after all the #elif directives. The basic form to use is:

#if defined(_  _win32_  _)

  const char os[] = "Microsoft Windows";

#elif defined(__linux__) or defined(_  _unix_  _)

  const char os[] = "UNIX (or variant)";

#elif defined(_  _vms_  _)

  const char os[] = "VMS";

#else

  const char os[] = "(unknown)";

#endif

Macros in the directive argument are expanded, except for the operands of the defined operator. The constant expression is evaluated, and if the result is nonzero, the #if condition is true, and the code in the region that immediately follows is compiled. The region ends with #else, #elif, or #endif. If the #if expression is false, the condition for the next #elif is evaluated, and if that expression is true, its region is compiled, and so on. If all #elif expressions are false, and #else is present, its region is compiled. Conditional processing ends with the corresponding #endif directive.

Conditionals can be nested. Within an inner region, the preprocessor keeps track of conditional directives even if the region is not being compiled, so conditional directives can be properly matched.

The #if and #elif directives take a single parameter, a constant expression. The expression differs slightly from non-preprocessor constant expressions:

  • You can use the defined operator.

  • Integers are long, that is, int values (and values that are promoted to int) have the same representation as long int, and unsigned int values have the same representation as unsigned long. All bool values are promoted to integers, including the keywords true and false.

  • Character literals are converted to the execution character set. The numeric value of a character in a preprocessor expression is not necessarily the same as the value of the same character in a non-preprocessor expression. A character may have a negative value.

  • Keywords that are alternative operators for symbolic operators (i.e., and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, and xor_eq) have their usual meaning, although it is ineffective to try using assignment operators (and_eq, or_eq, and xor_eq) in an #if or #elif condition.

  • Other identifiers and keywords that remain after macro expansion are replaced by 0. (It might seem strange to convert keywords, such as sizeof, to the integer 0, but that is the rule. Some compilers fail to follow this particular rule.) One consequence of this rule is that you cannot use type casts or new, delete, sizeof, throw, or typeid expressions in an #if or #elif condition.

Conditional directives are most often used to guard header files from multiple inclusion. All the standard headers are guarded, so including them more than once has no harmful effects. This is important because an implementation might include one header in another header. For example, <map> might include <utility> to get the declaration for the pair<> template. If you explicitly #include <map> and #include <utility>, you might end up including <utility> more than once.

Another common use is for system- or compiler-specific code. Every compiler predefines one or more macros to identify the compiler and possibly the host operating system (such as _ _linux_ _ or _ _GNUC_ _). Consult your compiler's documentation to learn which macro names are predefined.

Examples

Example 11-4 shows one way to nest conditional directives.

Example 11-4. Nesting conditional directives
#define zero zero  // Identifiers are converted to 0.

#define one  true  // Bool expressions are promoted to int.

#if one

// This region is compiled.

  #if zero

  This region can contain erroneous C++ code. The code is not

  compiled, so the errors do not matter.

  #else // This #else matches the inner #if.

    // This region is compiled.

    const int zero = 0;

  #endif // This #endif matches the inner #if.

  int x = zero;

#else

  This #else matches the outer #if. Because the #if

  condition was true, the #else region is not compiled.

#endif

You can guard your own headers by using conditional directives to define a guard macro and using the guard macro to ensure the file's contents are compiled only when the macro is not defined, as shown in Example 11-5.

Example 11-5. Guarding a header against multiple inclusion
// In the header file employee.h

#ifndef EMPLOYEE_H

#define EMPLOYEE_H

// Thus, the entire contents of the file are compiled only when EMPLOYEE_H is not

// defined. The first time the file is #included, the macro is not defined, in

// which case it is immediately defined. The second and subsequent times the same

// header is included in the same source file; the macro and conditional

// directives ensure that the entire file is skipped.

class employee { ... };

#endif  // End of employee.h

See Also

#elif directive, #else directive, #endif directive, #ifdef directive, #ifndef directive


#ifdef directive Tests whether a macro is defined
#ifdef identifier

The #ifdef directive begins a region of conditional compilation. It takes a single identifier as an argument and is equivalent to #if defined identifier.

See Also

defined operator, #if directive, #ifndef directive


#ifndef directive Tests whether a macro is undefined
#ifndef identifier

The #ifndef directive begins a region of conditional compilation. It takes a single identifier as an argument and is equivalent to #if not defined identifier.

See Also

defined operator, #if directive, #ifdef directive


#include directive Includes another source file
#include <header>

#include "sourcefile"

The #include directive includes the contents of a standard header or source file. The first form searches for header and replaces the directive with the entire contents of the header. The second form searches for sourcefile and replaces the directive with the entire contents of the named source file.

The basic action of #include is to read the named file or header as though its entire contents appeared in the source file at the position of the #include directive. Typically, common declarations are placed in a separate file, such as decl.h, and #include "decl.h" is used in every source file that depends on those declarations.

If a source file contains the directive #include "filename", and the compiler cannot find the external file named filename, the compiler also tries the form #include <filename>. Most compilers implement these two forms of #include by searching in different folders or directories. For example, the quote form searches in the current directory or in the directory that contains the source file, and the angle-bracket form searches only in "system" directories. Such details are implementation-defined, and some compilers might introduce further distinctions between the two forms.

It is possible, for example, for a compiler to recognize only the standard headers in the <header> form and use built-in knowledge of the standard headers without referencing any external files. This hypothetical compiler might report an error for all other uses of the angle-bracket form and require all external file inclusions to use the quote form. Such a compiler would not be very popular, however, because common practice is to treat <header> and "header" as equivalent forms, except when applying the rules for locating the external file named header.

It is common practice to install third-party libraries in common directories and to configure compilers to look in these directories for <header> inclusions. For example, if you use Boost (described in Appendix B), you might use #include <any.hpp> to obtain the boost::any class template. Another common practice is to install such libraries in subdirectories. On a Unix system, for example, you might install Boost in the boost subdirectory of one of the standard system directories and use #include <boost/any.hpp>. You should be careful, however, because using system-specific filenames is not portable.

The only guarantee that the standard offers is that if filename consists of a sequence of letters and underscore characters followed by a period and a single letter or underscore, then the implementation must provide a unique mapping of filename to a source file (optionally ignoring case distinctions). The standard permits universal characters in filename, but you should avoid them when you need maximum portability because some compilers do not support universal characters.

The implementation defines how and where the preprocessor searches for header or filename, how filename maps to an external filename, whether filenames heed or ignore case distinctions, and whether different character sequences for filename represent distinct external files. For example, under Windows, "foo.h" and "FOO.H" are usually the same file, but under Unix, they are usually different files. If the filesystem supports links, such as Unix, two names such as "foo.h" and "bar.h" might name the same file; in other environments, you might be guaranteed that different filenames refer to distinct files.

The most common convention is that <header> refers only to standard headers and to vendor-supplied extensions to the standard. Compilers typically have a way for you to supply your own additional libraries and use the associated headers as <header> includes. The quoted form is used for all header files that are part of the application, and those are typically located in the same directory or folder as the application's source files. The most common filename convention is to end header names with .h (for header), although .hpp is also common. For example, suppose you wrote a class to represent an employee. Put the class definition in employee.h and the definitions of the members in employee.cpp. Any other file that needs to use the employee class can #include "employee.h" and use the class definition:

#include <set>

#include "employee.h"

class business_group {

private:

  std::set<employee> employees_;

  ...

};

You can use other preprocessor tokens in an #include directive, provided they expand to one of the two standard forms. Each header name or filename must be a single preprocessor token; you cannot combine tokens to form a name. To preserve portability, use macros only for the entire sequence of the #include argument:

#define HEADER "this.h"

#include HEADER

See Also

#if directive


#line directive Changes the line number in error messages
#line digits

#line digits string

The #line directive changes the compiler's notion of the current filename and line number. The first form changes the line number (as expressed by the _ _LINE_ _ directive and used in error messages) to digits. The second form changes the line number to digits and the filename to the contents of string. The new file name is used as the value of the _ _FILE_ _ macro.

The #line directive is typically used by programs that generate C++ as output from some other input. The directive records the original filename and line number that produced the C++ code. Error messages and debuggers can point to the original file instead of to the intermediate C++ source file.

See Also

#error directive


#pragma directive Controls the compiler
#pragma tokens

The #pragma directive is implementation-defined. An implementation can define certain pragma parameters to control the compiler. The preprocessor ignores any pragma that it does not recognize.

Because pragmas are highly compiler-dependent, you should avoid using them as much as possible. Most compilers let you control the compiler by providing command-line options, configuration files, or project files. Do your best to keep compiler-specific information out of your source files. When you must use pragmas, protect them with conditional directives for specific compilers.

Example

#ifdef _  _BORLANDC_  _

  #pragma pack

#endif

#ifdef _  _COMO_  _

  #pragma instantiate

#endif


#undef directive Undefines a macro
#undef identifier

The #undef directive deletes the definition of the macro named identifier. If identifier is not a macro name, the directive has no effect. If you attempt to undefine the identifier defined or any predefined macro, the behavior is undefined.

See Also

#define directive