static_block.hpp 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /**
  2. * @file static_block.hpp
  3. *
  4. * @brief An implementation of a Java-style static block, in C++ (and potentially a
  5. * GCC/clang extension to avoid warnings).
  6. *
  7. * @note Partially inspired by Andrei Alexandrescu's Scope Guard and
  8. * discussions on stackoverflow.com
  9. *
  10. * By Eyal Rozenberg <eyalroz1@gmx.com>
  11. *
  12. * Licensed under the Apache License v2.0:
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. */
  16. #pragma once
  17. #ifndef STATIC_BLOCK_HPP_
  18. #define STATIC_BLOCK_HPP_
  19. #ifndef CONCATENATE
  20. #define CONCATENATE(s1, s2) s1##s2
  21. #define EXPAND_THEN_CONCATENATE(s1, s2) CONCATENATE(s1, s2)
  22. #endif /* CONCATENATE */
  23. #ifndef UNIQUE_IDENTIFIER
  24. /**
  25. * This macro expands into a different identifier in every expansion.
  26. * Note that you _can_ clash with an invocation of UNIQUE_IDENTIFIER
  27. * by manually using the same identifier elsewhere; or by carefully
  28. * choosing another prefix etc.
  29. */
  30. #ifdef __COUNTER__
  31. #define UNIQUE_IDENTIFIER(prefix) EXPAND_THEN_CONCATENATE(prefix, __COUNTER__)
  32. #else
  33. #define UNIQUE_IDENTIFIER(prefix) EXPAND_THEN_CONCATENATE(prefix, __LINE__)
  34. #endif /* COUNTER */
  35. #else
  36. #endif /* UNIQUE_IDENTIFIER */
  37. /**
  38. * Following is a mechanism for executing code statically.
  39. *
  40. * @note Caveats:
  41. * - Your static block must be surround by curly braces.
  42. * - No need for a semicolon after the block (but it won't hurt).
  43. * - Do not put static blocks in files, as it might get compiled multiple
  44. * times ane execute multiple times.
  45. * - A static_block can only be used in file scope - not within any other block etc.
  46. * - Templated static blocks will probably not work. Avoid them.
  47. * - No other funny business, this is fragile.
  48. * - This does not having any threading issues (AFAICT) - as it has no static
  49. * initialization order issue. Of course, you have to _keep_ it safe with
  50. * your static code.
  51. * - Execution of the code is guaranteed to occur before main() executes,
  52. * but the relative order of statics being initialized is unknown/unclear. So,
  53. * do not call any method of an instance of a class which you expect to have been
  54. * constructed; it may not have been. Instead, you can use a static getInstance() method
  55. * (look this idiom up on the web, it's safe).
  56. * - Variables defined within the static block are not global; they will
  57. * go out of scope as soon as its execution concludes.
  58. *
  59. * Usage example:
  60. *
  61. * static_block {
  62. * do_stuff();
  63. * std::cout << "in the static block!\n";
  64. * }
  65. *
  66. */
  67. #define static_block STATIC_BLOCK_IMPL1(UNIQUE_IDENTIFIER(_static_block_))
  68. #define STATIC_BLOCK_IMPL1(prefix) \
  69. STATIC_BLOCK_IMPL2(CONCATENATE(prefix,_fn),CONCATENATE(prefix,_var))
  70. #define STATIC_BLOCK_IMPL2(function_name,var_name) \
  71. static void function_name(); \
  72. static int var_name __attribute((unused)) = (function_name(), 0) ; \
  73. static void function_name()
  74. #endif // STATIC_BLOCK_HPP_