#include <type_traits>
namespace detail{
template<int> struct sfinae_true : std::true_type{};
template<class T>
sfinae_true<(T::f(), 0)> check(int);
template<class>
std::false_type check(...);
} // detail::
template<class T>
struct has_constexpr_f : decltype(detail::check<T>(0)){};
struct trait
{
static int f(){ return 15; }
};
struct ctrait
{
static constexpr int f(){ return 20; }
};
static_assert(has_constexpr_f<trait>() == false, "trait");
static_assert(has_constexpr_f<ctrait>() == true, "ctrait");
int main(){}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKbmFtZXNwYWNlIGRldGFpbHsKdGVtcGxhdGU8aW50PiBzdHJ1Y3Qgc2ZpbmFlX3RydWUgOiBzdGQ6OnRydWVfdHlwZXt9Owp0ZW1wbGF0ZTxjbGFzcyBUPgpzZmluYWVfdHJ1ZTwoVDo6ZigpLCAwKT4gY2hlY2soaW50KTsKdGVtcGxhdGU8Y2xhc3M+CnN0ZDo6ZmFsc2VfdHlwZSBjaGVjayguLi4pOwp9IC8vIGRldGFpbDo6Cgp0ZW1wbGF0ZTxjbGFzcyBUPgpzdHJ1Y3QgaGFzX2NvbnN0ZXhwcl9mIDogZGVjbHR5cGUoZGV0YWlsOjpjaGVjazxUPigwKSl7fTsKCnN0cnVjdCB0cmFpdAp7CiAgICBzdGF0aWMgaW50IGYoKXsgcmV0dXJuIDE1OyB9Cn07CgpzdHJ1Y3QgY3RyYWl0CnsKICAgIHN0YXRpYyBjb25zdGV4cHIgaW50IGYoKXsgcmV0dXJuIDIwOyB9Cn07CgpzdGF0aWNfYXNzZXJ0KGhhc19jb25zdGV4cHJfZjx0cmFpdD4oKSA9PSBmYWxzZSwgInRyYWl0Iik7CnN0YXRpY19hc3NlcnQoaGFzX2NvbnN0ZXhwcl9mPGN0cmFpdD4oKSA9PSB0cnVlLCAiY3RyYWl0Iik7CgppbnQgbWFpbigpe30K