vmd_identifier.qbk 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. [/
  2. (C) Copyright Edward Diener 2011-2015
  3. Distributed under the Boost Software License, Version 1.0.
  4. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. ]
  7. [section:vmd_identifier Identifiers]
  8. An identifier in VMD is either of two lower-level preprocessor possibilities:
  9. * a preprocessing token 'identifier', which is essentially a sequence
  10. of alphanumeric characters and the underscore
  11. character with the first character not being a numeric character.
  12. * a preprocessing token 'pp-number' that is an integral literal token.
  13. Here are some examples:
  14. SOME_NAME
  15. _SOME_NAME
  16. SOME_123_NAME
  17. some_123_name
  18. sOMe_123_NAmE
  19. 2367
  20. 43e11
  21. 0
  22. 22
  23. 654792
  24. 0x1256
  25. [heading Problem testing any identifier]
  26. One of the difficulties with identifiers in preprocessor metaprogramming
  27. is safely testing for a particular one. VMD has a means of doing this within
  28. a particular constraint for the characters that serve as the input.
  29. The constraint is that the beginning input character, ignoring any whitespace, passed
  30. as the input to test must be either:
  31. * an identifier character, ie. an alphanumeric or an underscore
  32. * the left parenthesis of a tuple
  33. and if the first character is not the left parenthesis of a tuple
  34. the remaining characters must be alphanumeric or an underscore until a space character
  35. or end of input occurs.
  36. If this is not the case the behavior is undefined, and most likely
  37. a preprocessing error will occur.
  38. Given the input:
  39. 's_anything' : can be tested
  40. 'S_anything' : can be tested
  41. 's_anYthiNg' : can be tested
  42. '_anything' : can be tested
  43. '_Anything' : can be tested
  44. '_anytHIng' : can be tested
  45. '24' : can be tested
  46. '245e2' : can be tested
  47. '(anything)' : can be tested, tuple
  48. '(anything) anything' : can be tested, tuple and further input
  49. 'anything anything' : can be tested, identifier followed by space character
  50. '%_anything' : undefined behavior and most likely a preprocessing error due to the constraint
  51. '(_anything' : undefined behavior and most likely a preprocessing error due to the constraint, since a single '(' does not form a tuple
  52. '44.3' : undefined behavior and most likely a preprocessing error due to the constraint since '.' is not alphanumeric
  53. [heading Identifying an identifier]
  54. In VMD the only way an identifier can be identified in preprocessor input is by a process called
  55. registration. In order to 'register' an identifier to be recognized by VMD the end-user must create,
  56. for every identifier to be recognized, an object-like macro whose form is:
  57. #define BOOST_VMD_REGISTER_identifier (identifier)
  58. where 'identifier' is a particular identifier we wish to identify. This is called in
  59. VMD a registration macro.
  60. It is recommended that such registration macros be created in a header file which
  61. can be included before the end-user uses the identifier macros of VMD.
  62. If a particular registration macro occurs more than once it is
  63. not a preprocessing error, so duplicating a registration macro will not lead to any problems
  64. since each registration macro of the same name will have the exact same object-like macro
  65. expansion.
  66. Within a given translation unit it could potentially happen
  67. that registration macros have been included by header files which a particular end-user
  68. of VMD has not created. This should also not lead to particular problems since registration
  69. is a process for adding identifiers for any particular translation unit. As we shall see
  70. VMD has macros for not only finding any identifier in preprocessor input but for also finding
  71. any particular identifier in preprocessor input.
  72. [heading Testing for an identifier macro]
  73. The specific macro used to test for an identifier in VMD is called BOOST_VMD_IS_IDENTIFIER.
  74. The macro takes one required parameter which is the input against which to test.
  75. When we invoke BOOST_VMD_IS_IDENTIFIER it returns 1 if the input represents any
  76. registered identifier, otherwise it returns 0.
  77. As an example:
  78. #include <boost/vmd/is_identifier.hpp>
  79. #define BOOST_VMD_REGISTER_yellow (yellow)
  80. #define BOOST_VMD_REGISTER_green (green)
  81. #define BOOST_VMD_REGISTER_blue (blue)
  82. BOOST_VMD_IS_IDENTIFIER(some_input) // returns 1 if 'some_input' is 'yellow','green', or 'blue'
  83. BOOST_VMD_IS_IDENTIFIER(some_input) // returns 0 if 'some_input' is 'purple'
  84. Essentially only registered identifiers can be found in VMD as identifiers.
  85. [heading Detecting a particular identifier]
  86. Although registering an identifier allows VMD to recognize the string of characters
  87. as a VMD identifier, the ability to detect a particular identifier needs the end-user
  88. to define another macro:
  89. #define BOOST_VMD_DETECT_identifier_identifier
  90. where 'identifier' is a particular identifier we wish to detect. This object-like
  91. macro expands to no output.
  92. Like the registration macro multiple detection macros of the same identifier
  93. in a translation unit does not cause a compiler problem since the exact same
  94. object-like macro occurs.
  95. The term for creating this macro is that we have potentially 'pre-detected'
  96. the identifier and I will use the term pre-detected as the process of creating
  97. the BOOST_VMD_DETECT macro.
  98. The ability to detect that a VMD identifier is a particular identifier is used
  99. in VMD macros when data is compared for equality/inequality as well as when we
  100. want to match an identifier against a set of other identifiers. These situations
  101. will be explained later in the documentation when the particular macro functionality
  102. is discussed. If the programmer never uses the functionality which these situations
  103. encompass there is no need to use pre-detection for a registered identifier.
  104. [heading Parsing identifiers and undefined behavior]
  105. The technique for parsing identifiers, once it is determined that the input
  106. being parsed does not begin with a set of parentheses, uses preprocessor
  107. concatenation in its parsing. This technique involves the preprocessor '##'
  108. operator to concatenate input, and examine the results of that concatenation.
  109. When preprocessor concatenation is used the result of the concatenation must
  110. be a valid preprocessing token, else the behavior of the preprocessor is undefined.
  111. In C++ 'undefined behavior' in general means that anything can happen. In practical
  112. use when preprocessor concatenation does not produce a valid preprocessing token,
  113. a compiler is most likely to generate a preprocessing error. If the compiler chooses
  114. not to issue a preprocessing error the outcome will always mean that parsing an
  115. identifier will fail. But because the outcome is undefined behavior there is no
  116. absolute way that the programmer can determine what the outcome will be when
  117. preprocessor concatenation is used and the input being parsed contains
  118. preprocessor input which does not meet the constraints for parsing an identifier
  119. mentioned at the beginning of this topic.
  120. In this documentation I will be using the abbreviation 'UB' as the shortened form
  121. of 'undefined behavior' to denote the particular occurrence where VMD attempts to
  122. parse preprocessor input using preprocessor concatenation and undefined behavior
  123. will occur.
  124. [heading Usage]
  125. To use the BOOST_VMD_IS_IDENTIFIER macro either include the general header:
  126. #include <boost/vmd/vmd.hpp>
  127. or include the specific header:
  128. #include <boost/vmd/is_identifier.hpp>
  129. [endsect]