#include #include #include struct A {}; template struct type_constant; template struct invocable_base { constexpr R operator()(Args... args) const { return std::invoke(F, std::forward(args)...); } }; template constexpr bool is_noexcept = noexcept(F()); #if __clang__ #elif __GCC__ template constexpr bool is_noexcept = false; template constexpr bool is_noexcept = true; #endif template struct type_constant { static constexpr bool is_noexcept = noexcept(Fun(std::declval()...)); constexpr R operator()(Args... args) const noexcept(is_noexcept) { return Fun(std::forward(args)...); } constexpr operator decltype(Fun)() const noexcept { return Fun; } }; #if 0 && __clang__ template struct type_constant { static constexpr bool is_noexcept = true; constexpr R operator()(Args... args) const noexcept(is_noexcept) { return Fun(std::forward(args)...); } constexpr operator decltype(Fun)() const noexcept { return Fun; } }; #endif extern "C" void free_a(A* a) noexcept { delete a; } using free_a_t = type_constant; void non_except() noexcept(true) {} void except() noexcept(false) {} static_assert(sizeof(free_a_t) == 1); // static_assert(free_a_t::is_noexcept); static_assert(!type_constant::is_noexcept); static_assert(is_noexcept); static_assert(!is_noexcept); static_assert(sizeof(std::unique_ptr) == sizeof(std::unique_ptr)); // static_assert(std::is_same_v); static_assert(std::is_same_v); int deleter_main(int, char**) { free_a_t f; f(nullptr); A* a = nullptr; f(a); f(new A); return 0; } namespace a { namespace { template struct is_noexcept; template struct is_noexcept { constexpr static bool value = noexcept(F(std::declval()...)); }; template constexpr bool is_noexcept_v = is_noexcept::value; void non_except() noexcept(true) {} void except() noexcept(false) {} // static_assert(is_noexcept_v); static_assert(!is_noexcept_v); } // namespace } // namespace a