fork download
  1. #include <utility>
  2.  
  3. template <class T>
  4. constexpr bool always_true(T&&) { return true; }
  5.  
  6. template<bool>
  7. struct always_bool { using type = bool; };
  8.  
  9. template <class T, class U>
  10. constexpr bool true_if_constexpr(T, U) { return false; }
  11.  
  12. template <class U>
  13. constexpr auto true_if_constexpr(int, U)
  14. -> typename always_bool
  15. < ::always_true(decltype(std::declval<U>()()){}.member) >::type
  16. {
  17. return true;
  18. }
  19.  
  20. struct empty {};
  21.  
  22. #define IS_CONSTEXPR(decl, expr) \
  23. (::true_if_constexpr(0, \
  24.  [] \
  25.  { \
  26. TYPE(decl) NAME(decl); \
  27.   \
  28. struct return_type \
  29. { \
  30. decltype(expr)&& member = static_cast<decltype(expr)&&>(expr); \
  31. }; \
  32.   \
  33. return return_type{}; \
  34.  }) \
  35. )
  36.  
  37.  
  38. #define IS_INVALID_EXPR(decl, expr) (!IS_VALID_EXPR(decl,expr))
  39.  
  40. #define FIRST_ARG_EXPANDED_(a,b) FORWARD a
  41. #define FIRST_ARG_EXPANDED(...) FIRST_ARG_EXPANDED_(__VA_ARGS__)
  42.  
  43. #define SECOND_ARG_EXPANDED_(a,b) b
  44. #define SECOND_ARG_EXPANDED(...) SECOND_ARG_EXPANDED_(__VA_ARGS__)
  45.  
  46. #define PARENTHESIZED_PART_(...) (__VA_ARGS__),
  47. #define TYPE(arg) FIRST_ARG_EXPANDED( PARENTHESIZED_PART_ arg )
  48.  
  49. #define NAME(arg) SECOND_ARG_EXPANDED( PARENTHESIZED_PART_ arg )
  50.  
  51. #define STRINGIZE_(...) #__VA_ARGS__
  52. #define STRINGIZE(...) STRINGIZE_(__VA_ARGS__)
  53.  
  54. #define FORWARD(...) __VA_ARGS__
  55.  
  56. template<class T>
  57. bool foo(T&&) { return true; }
  58.  
  59. template<class T>
  60. constexpr bool constexpr_foo(T&&) { return true; }
  61.  
  62. #define STATIC_ASSERT_CONSTEXPR_(n, f, s, decl, expr) \
  63. (n IS_CONSTEXPR(decl, expr), \
  64. "\n\n********************\n\n" \
  65. "Given:\n " STRINGIZE(TYPE(decl)) " " STRINGIZE(NAME(decl)) ";\n\n" \
  66. "The following expression was expected to" f " be constexpr but was" s ":\n" \
  67. " " STRINGIZE(expr) "\n\n********************")
  68.  
  69. #define STATIC_ASSERT_CONSTEXPR(decl, expr) \
  70. static_assert \
  71. STATIC_ASSERT_CONSTEXPR_(, , " not", decl, expr)
  72.  
  73. #define STATIC_ASSERT_NOT_CONSTEXPR(decl, expr) \
  74. static_assert \
  75. STATIC_ASSERT_CONSTEXPR_(!, " not", , decl, expr)
  76.  
  77. STATIC_ASSERT_CONSTEXPR
  78. (
  79. (constexpr int) var = 5,
  80. constexpr_foo(var)
  81. );
  82.  
  83.  
  84. STATIC_ASSERT_NOT_CONSTEXPR
  85. (
  86. (constexpr int) var = 5,
  87. foo(var)
  88. );
  89.  
  90. int main() {}
  91.  
Success #stdin #stdout 0s 3092KB
stdin
Standard input is empty
stdout
Standard output is empty