1 // PR c++/82218
2 // { dg-do compile { target c++14 } }
3 // { dg-options "-fdelete-null-pointer-checks" }
4
5 template<typename _Tp>
6 struct identity
7 {
8 typedef _Tp type;
9 };
10
11 template<typename _Tp>
12 inline _Tp&&
forward(typename identity<_Tp>::type && __t)13 forward(typename identity<_Tp>::type&& __t)
14 { return __t; }
15
16 template < typename T >
17 class delegate;
18
19 template < typename R, typename... Params >
20 class delegate< R(Params...) > final
21 {
22 private:
23 using CallbackType = R (*)(void*, Params...);
24
25 using FunctionPtr = R (*)(Params...);
26
27 template < typename Object >
28 using MethodPtr = R (Object::*)(Params...);
29
30 template < typename Object >
31 using ConstMethodPtr = R (Object::*)(Params...) const;
32
33 void* obj_;
34 CallbackType cb_;
35
36 template < typename Object, MethodPtr< Object > Mptr >
invoke_method(void * obj,Params...params)37 constexpr static R invoke_method(void* obj, Params... params) noexcept(
38 noexcept((static_cast< Object* >(obj)->*Mptr)(params...)))
39 {
40 return (static_cast< Object* >(obj)->*Mptr)(params...);
41 }
42
43 template < typename Object, ConstMethodPtr< Object > Mptr >
invoke_method(void * obj,Params...params)44 constexpr static R invoke_method(void* obj, Params... params) noexcept(
45 noexcept((static_cast< Object* >(obj)->*Mptr)(params...)))
46 {
47 return (static_cast< Object* >(obj)->*Mptr)(params...);
48 }
49
50 template < FunctionPtr Fptr >
invoke_function(void *,Params...params)51 constexpr static R invoke_function(void*, Params... params) noexcept(
52 noexcept((*Fptr)(params...)))
53 {
54 return (*Fptr)(params...);
55 }
56
delegate(void * obj,CallbackType callback)57 constexpr delegate(void* obj, CallbackType callback) noexcept : obj_(obj),
58 cb_(callback)
59 {
60 }
61
error_function(Params...)62 constexpr static R error_function(Params...)
63 {
64 while(1);
65 }
66
67 public:
68 using base_type = delegate< R(Params...) >;
69
delegate()70 delegate()
71 {
72 *this = from< error_function >();
73 }
74
75 delegate(const base_type&) = default;
76 delegate(base_type&&) = default;
77
78 base_type& operator=(const base_type&) = default;
79 base_type& operator=(base_type&&) = default;
80
81 template < typename Object, MethodPtr< Object > Mptr >
from(Object & obj)82 constexpr static auto from(Object& obj) noexcept
83 {
84 return delegate(&obj, &invoke_method< Object, Mptr >);
85 }
86
87 template < typename Object, ConstMethodPtr< Object > Mptr >
from(Object & obj)88 constexpr static auto from(Object& obj) noexcept
89 {
90 return delegate(&obj, &invoke_method< Object, Mptr >);
91 }
92
93 template < FunctionPtr Fptr >
from()94 constexpr static auto from() noexcept
95 {
96 static_assert(Fptr != nullptr, "Function pointer must not be null");
97
98 return delegate(nullptr, &invoke_function< Fptr >);
99 }
100
101 template < typename... Args >
operator()102 constexpr auto operator()(Args&&... params) const
103 noexcept(noexcept((*cb_)(obj_, forward< Args >(params)...)))
104 {
105 return (*cb_)(obj_, forward< Args >(params)...);
106 }
107
valid()108 constexpr bool valid() const noexcept
109 {
110 return (cb_ != &invoke_function< error_function >);
111 }
112
113 constexpr bool operator==(const delegate& other) const noexcept
114 {
115 return (obj_ == other.obj_) && (cb_ == other.cb_);
116 }
117
118 constexpr bool operator!=(const delegate& other) const noexcept
119 {
120 return (obj_ != other.obj_) || (cb_ != other.cb_);
121 }
122 };
123
124 delegate< void(void) > a;
125
test()126 void test()
127 {
128 a();
129 }
130