fork(1) download
  1. #include <type_traits>
  2. #include <utility>
  3.  
  4. template <class T>
  5. constexpr bool returns_true(const T fun) {
  6. return decltype(fun())::value;
  7. }
  8.  
  9. template <class T>
  10. struct true_if_callable_t : T {
  11. using T::operator();
  12. template<class...P>
  13. std::false_type operator()(P&&...) const;
  14. };
  15.  
  16. template<class T, class... P>
  17. [[noreturn]] auto true_if_callable(T, P&&...a)
  18. -> decltype(std::declval<true_if_callable_t<T>>()(0, std::declval<P>()...)) {}
  19.  
  20. template<class>
  21. struct always_true_type { using type = std::true_type; };
  22.  
  23. template <class T>
  24. [[noreturn]] T&& declv() {}
  25.  
  26. #define FORWARD(...) __VA_ARGS__
  27.  
  28. #define IS_VALID_EXPR(decl, expr) \
  29. ::returns_true([]{ return true_if_callable( [](int,auto&& NAME(decl)) \
  30. -> typename always_true_type<decltype(expr)>::type { \
  31.   return std::true_type{}; \
  32.   }, ::declv<TYPE(decl)>() ); })
  33.  
  34. #define IS_INVALID_EXPR(decl, expr) (!IS_VALID_EXPR(decl,expr))
  35.  
  36. #define FIRST_ARG_EXPANDED_(a,b) FORWARD a
  37. #define FIRST_ARG_EXPANDED(...) FIRST_ARG_EXPANDED_(__VA_ARGS__)
  38.  
  39. #define SECOND_ARG_EXPANDED_(a,b) b
  40. #define SECOND_ARG_EXPANDED(...) SECOND_ARG_EXPANDED_(__VA_ARGS__)
  41.  
  42. #define PARENTHESIZED_PART_(...) (__VA_ARGS__),
  43. #define TYPE(arg) FIRST_ARG_EXPANDED( PARENTHESIZED_PART_ arg )
  44.  
  45. #define NAME(arg) SECOND_ARG_EXPANDED( PARENTHESIZED_PART_ arg )
  46.  
  47. #define STRINGIZE_(...) #__VA_ARGS__
  48. #define STRINGIZE(...) STRINGIZE_(__VA_ARGS__)
  49.  
  50. #define STATIC_ASSERT_VALID_(n, f, s, decl, expr) \
  51. (n IS_VALID_EXPR(decl, expr), \
  52. "\n\n********************\n\n" \
  53. "Given:\n " STRINGIZE(TYPE(decl)) " " STRINGIZE(NAME(decl)) ";\n\n" \
  54. "The following expression was expected to" f " compile but did" s ":\n " \
  55. STRINGIZE(expr) "\n\n********************")
  56.  
  57. #define STATIC_ASSERT_VALID(decl, expr) \
  58. static_assert \
  59. STATIC_ASSERT_VALID_(, , " not", decl, expr)
  60.  
  61. #define STATIC_ASSERT_INVALID(decl, expr) \
  62. static_assert \
  63. STATIC_ASSERT_VALID_(!, " not", , decl, expr)
  64.  
  65.  
  66. STATIC_ASSERT_VALID
  67. (
  68. (int) a,
  69. ++a
  70. );
  71.  
  72.  
  73. STATIC_ASSERT_INVALID
  74. (
  75. (const int) a,
  76. ++a
  77. );
  78.  
  79.  
  80. int main() {}
  81.  
Success #stdin #stdout 0s 3092KB
stdin
Standard input is empty
stdout
Standard output is empty