#include <type_traits>
#include <utility>
 
template <class T>
constexpr bool returns_true(const T fun) {
	return decltype(fun())::value;
}
 
template <class T>
struct true_if_callable_t : T {
	using T::operator();
	template<class...P>
	std::false_type operator()(P&&...) const;
};
 
template<class T, class... P>
[[noreturn]] auto true_if_callable(T, P&&...a)
-> decltype(std::declval<true_if_callable_t<T>>()(0, std::declval<P>()...)) {}
 
template<class>
struct always_true_type { using type = std::true_type; };
 
template <class T>
[[noreturn]] T&& declv() {}
 
#define FORWARD(...) __VA_ARGS__
 
#define IS_VALID_EXPR(decl, expr)                                              \
::returns_true([]{ return true_if_callable( [](int,auto&& NAME(decl))          \
-> typename always_true_type<decltype(expr)>::type {                           \
        return std::true_type{};                                               \
    }, ::declv<TYPE(decl)>() );   })
 
#define IS_INVALID_EXPR(decl, expr) (!IS_VALID_EXPR(decl,expr))
 
#define FIRST_ARG_EXPANDED_(a,b) FORWARD a
#define FIRST_ARG_EXPANDED(...) FIRST_ARG_EXPANDED_(__VA_ARGS__)
 
#define SECOND_ARG_EXPANDED_(a,b) b
#define SECOND_ARG_EXPANDED(...) SECOND_ARG_EXPANDED_(__VA_ARGS__)
 
#define PARENTHESIZED_PART_(...) (__VA_ARGS__),
#define TYPE(arg) FIRST_ARG_EXPANDED( PARENTHESIZED_PART_ arg )
 
#define NAME(arg) SECOND_ARG_EXPANDED( PARENTHESIZED_PART_ arg )
 
#define STRINGIZE_(...) #__VA_ARGS__
#define STRINGIZE(...) STRINGIZE_(__VA_ARGS__)
 
#define STATIC_ASSERT_VALID_(n, f, s, decl, expr)                              \
(n IS_VALID_EXPR(decl, expr),                                                              \
"\n\n********************\n\n"                                                 \
"Given:\n    " STRINGIZE(TYPE(decl)) " " STRINGIZE(NAME(decl)) ";\n\n"         \
"The following expression was expected to" f " compile but did" s ":\n    "    \
STRINGIZE(expr) "\n\n********************")
 
#define STATIC_ASSERT_VALID(decl, expr)                                        \
static_assert                                                                  \
STATIC_ASSERT_VALID_(, , " not", decl, expr)
 
#define STATIC_ASSERT_INVALID(decl, expr)                                      \
static_assert                                                                  \
STATIC_ASSERT_VALID_(!, " not", , decl, expr)
 
 
STATIC_ASSERT_VALID
(
    (int) a,
    ++a
);
 
 
STATIC_ASSERT_INVALID
(
    (const int) a,
    ++a
);
 
 
int main() {}
 
				I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8dXRpbGl0eT4KCnRlbXBsYXRlIDxjbGFzcyBUPgpjb25zdGV4cHIgYm9vbCByZXR1cm5zX3RydWUoY29uc3QgVCBmdW4pIHsKCXJldHVybiBkZWNsdHlwZShmdW4oKSk6OnZhbHVlOwp9Cgp0ZW1wbGF0ZSA8Y2xhc3MgVD4Kc3RydWN0IHRydWVfaWZfY2FsbGFibGVfdCA6IFQgewoJdXNpbmcgVDo6b3BlcmF0b3IoKTsKCXRlbXBsYXRlPGNsYXNzLi4uUD4KCXN0ZDo6ZmFsc2VfdHlwZSBvcGVyYXRvcigpKFAmJi4uLikgY29uc3Q7Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcy4uLiBQPgpbW25vcmV0dXJuXV0gYXV0byB0cnVlX2lmX2NhbGxhYmxlKFQsIFAmJi4uLmEpCi0+IGRlY2x0eXBlKHN0ZDo6ZGVjbHZhbDx0cnVlX2lmX2NhbGxhYmxlX3Q8VD4+KCkoMCwgc3RkOjpkZWNsdmFsPFA+KCkuLi4pKSB7fQoKdGVtcGxhdGU8Y2xhc3M+CnN0cnVjdCBhbHdheXNfdHJ1ZV90eXBlIHsgdXNpbmcgdHlwZSA9IHN0ZDo6dHJ1ZV90eXBlOyB9OwoKdGVtcGxhdGUgPGNsYXNzIFQ+Cltbbm9yZXR1cm5dXSBUJiYgZGVjbHYoKSB7fQoKI2RlZmluZSBGT1JXQVJEKC4uLikgX19WQV9BUkdTX18KCiNkZWZpbmUgSVNfVkFMSURfRVhQUihkZWNsLCBleHByKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCjo6cmV0dXJuc190cnVlKFtdeyByZXR1cm4gdHJ1ZV9pZl9jYWxsYWJsZSggW10oaW50LGF1dG8mJiBOQU1FKGRlY2wpKSAgICAgICAgICBcCi0+IHR5cGVuYW1lIGFsd2F5c190cnVlX3R5cGU8ZGVjbHR5cGUoZXhwcik+Ojp0eXBlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgcmV0dXJuIHN0ZDo6dHJ1ZV90eXBle307ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICB9LCA6OmRlY2x2PFRZUEUoZGVjbCk+KCkgKTsgICB9KQoKI2RlZmluZSBJU19JTlZBTElEX0VYUFIoZGVjbCwgZXhwcikgKCFJU19WQUxJRF9FWFBSKGRlY2wsZXhwcikpCgojZGVmaW5lIEZJUlNUX0FSR19FWFBBTkRFRF8oYSxiKSBGT1JXQVJEIGEKI2RlZmluZSBGSVJTVF9BUkdfRVhQQU5ERUQoLi4uKSBGSVJTVF9BUkdfRVhQQU5ERURfKF9fVkFfQVJHU19fKQoKI2RlZmluZSBTRUNPTkRfQVJHX0VYUEFOREVEXyhhLGIpIGIKI2RlZmluZSBTRUNPTkRfQVJHX0VYUEFOREVEKC4uLikgU0VDT05EX0FSR19FWFBBTkRFRF8oX19WQV9BUkdTX18pCgojZGVmaW5lIFBBUkVOVEhFU0laRURfUEFSVF8oLi4uKSAoX19WQV9BUkdTX18pLAojZGVmaW5lIFRZUEUoYXJnKSBGSVJTVF9BUkdfRVhQQU5ERUQoIFBBUkVOVEhFU0laRURfUEFSVF8gYXJnICkKCiNkZWZpbmUgTkFNRShhcmcpIFNFQ09ORF9BUkdfRVhQQU5ERUQoIFBBUkVOVEhFU0laRURfUEFSVF8gYXJnICkKCiNkZWZpbmUgU1RSSU5HSVpFXyguLi4pICNfX1ZBX0FSR1NfXwojZGVmaW5lIFNUUklOR0laRSguLi4pIFNUUklOR0laRV8oX19WQV9BUkdTX18pCgojZGVmaW5lIFNUQVRJQ19BU1NFUlRfVkFMSURfKG4sIGYsIHMsIGRlY2wsIGV4cHIpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAoobiBJU19WQUxJRF9FWFBSKGRlY2wsIGV4cHIpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAoiXG5cbioqKioqKioqKioqKioqKioqKioqXG5cbiIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAoiR2l2ZW46XG4gICAgIiBTVFJJTkdJWkUoVFlQRShkZWNsKSkgIiAiIFNUUklOR0laRShOQU1FKGRlY2wpKSAiO1xuXG4iICAgICAgICAgXAoiVGhlIGZvbGxvd2luZyBleHByZXNzaW9uIHdhcyBleHBlY3RlZCB0byIgZiAiIGNvbXBpbGUgYnV0IGRpZCIgcyAiOlxuICAgICIgICAgXApTVFJJTkdJWkUoZXhwcikgIlxuXG4qKioqKioqKioqKioqKioqKioqKiIpCgojZGVmaW5lIFNUQVRJQ19BU1NFUlRfVkFMSUQoZGVjbCwgZXhwcikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXApzdGF0aWNfYXNzZXJ0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXApTVEFUSUNfQVNTRVJUX1ZBTElEXygsICwgIiBub3QiLCBkZWNsLCBleHByKQoKI2RlZmluZSBTVEFUSUNfQVNTRVJUX0lOVkFMSUQoZGVjbCwgZXhwcikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKc3RhdGljX2Fzc2VydCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKU1RBVElDX0FTU0VSVF9WQUxJRF8oISwgIiBub3QiLCAsIGRlY2wsIGV4cHIpCgoKU1RBVElDX0FTU0VSVF9WQUxJRAooCiAgICAoaW50KSBhLAogICAgKythCik7CgoKU1RBVElDX0FTU0VSVF9JTlZBTElECigKICAgIChjb25zdCBpbnQpIGEsCiAgICArK2EKKTsKCgppbnQgbWFpbigpIHt9Cg==