is_nothrow_invocable.pass.cpp (4315B)
1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: c++98, c++03, c++11, c++14 11 12 // type_traits 13 14 // is_nothrow_invocable 15 16 #include <type_traits> 17 #include <functional> 18 19 #include "test_macros.h" 20 21 struct Tag {}; 22 23 struct Implicit { 24 Implicit(int) noexcept {} 25 }; 26 27 struct ThrowsImplicit { 28 ThrowsImplicit(int) {} 29 }; 30 31 struct Explicit { 32 explicit Explicit(int) noexcept {} 33 }; 34 35 template <bool IsNoexcept, class Ret, class ...Args> 36 struct CallObject { 37 Ret operator()(Args&&...) const noexcept(IsNoexcept); 38 }; 39 40 template <class Fn, class ...Args> 41 constexpr bool throws_invocable() { 42 return std::is_invocable<Fn, Args...>::value && 43 !std::is_nothrow_invocable<Fn, Args...>::value; 44 } 45 46 template <class Ret, class Fn, class ...Args> 47 constexpr bool throws_invocable_r() { 48 return std::is_invocable_r<Ret, Fn, Args...>::value && 49 !std::is_nothrow_invocable_r<Ret, Fn, Args...>::value; 50 } 51 52 // FIXME(EricWF) Don't test the where noexcept is *not* part of the type system 53 // once implementations have caught up. 54 void test_noexcept_function_pointers() 55 { 56 struct Dummy { void foo() noexcept {} static void bar() noexcept {} }; 57 #if !defined(__cpp_noexcept_function_type) 58 { 59 // Check that PMF's and function pointers *work*. is_nothrow_invocable will always 60 // return false because 'noexcept' is not part of the function type. 61 static_assert(throws_invocable<decltype(&Dummy::foo), Dummy&>(), ""); 62 static_assert(throws_invocable<decltype(&Dummy::bar)>(), ""); 63 } 64 #else 65 { 66 // Check that PMF's and function pointers actually work and that 67 // is_nothrow_invocable returns true for noexcept PMF's and function 68 // pointers. 69 static_assert(std::is_nothrow_invocable<decltype(&Dummy::foo), Dummy&>::value, ""); 70 static_assert(std::is_nothrow_invocable<decltype(&Dummy::bar)>::value, ""); 71 } 72 #endif 73 } 74 75 int main() 76 { 77 { 78 // Check that the conversion to the return type is properly checked 79 using Fn = CallObject<true, int>; 80 static_assert(std::is_nothrow_invocable_r<Implicit, Fn>::value, ""); 81 static_assert(std::is_nothrow_invocable_r<double, Fn>::value, ""); 82 static_assert(std::is_nothrow_invocable_r<const volatile void, Fn>::value, ""); 83 static_assert(throws_invocable_r<ThrowsImplicit, Fn>(), ""); 84 static_assert(!std::is_nothrow_invocable<Fn(), Explicit>(), ""); 85 } 86 { 87 // Check that the conversion to the parameters is properly checked 88 using Fn = CallObject<true, void, const Implicit&, const ThrowsImplicit&>; 89 static_assert(std::is_nothrow_invocable<Fn, Implicit&, ThrowsImplicit&>::value, ""); 90 static_assert(std::is_nothrow_invocable<Fn, int, ThrowsImplicit&>::value, ""); 91 static_assert(throws_invocable<Fn, int, int>(), ""); 92 static_assert(!std::is_nothrow_invocable<Fn>::value, ""); 93 } 94 { 95 // Check that the noexcept-ness of function objects is checked. 96 using Fn = CallObject<true, void>; 97 using Fn2 = CallObject<false, void>; 98 static_assert(std::is_nothrow_invocable<Fn>::value, ""); 99 static_assert(throws_invocable<Fn2>(), ""); 100 } 101 { 102 // Check that PMD derefs are noexcept 103 using Fn = int (Tag::*); 104 static_assert(std::is_nothrow_invocable<Fn, Tag&>::value, ""); 105 static_assert(std::is_nothrow_invocable_r<Implicit, Fn, Tag&>::value, ""); 106 static_assert(throws_invocable_r<ThrowsImplicit, Fn, Tag&>(), ""); 107 } 108 { 109 // Check for is_nothrow_invocable_v 110 using Fn = CallObject<true, int>; 111 static_assert(std::is_nothrow_invocable_v<Fn>, ""); 112 static_assert(!std::is_nothrow_invocable_v<Fn, int>, ""); 113 } 114 { 115 // Check for is_nothrow_invocable_r_v 116 using Fn = CallObject<true, int>; 117 static_assert(std::is_nothrow_invocable_r_v<void, Fn>, ""); 118 static_assert(!std::is_nothrow_invocable_r_v<int, Fn, int>, ""); 119 } 120 test_noexcept_function_pointers(); 121 }