| // PR c++/82218 |
| // { dg-do compile { target c++14 } } |
| // { dg-options "-fdelete-null-pointer-checks" } |
| |
| template<typename _Tp> |
| struct identity |
| { |
| typedef _Tp type; |
| }; |
| |
| template<typename _Tp> |
| inline _Tp&& |
| forward(typename identity<_Tp>::type&& __t) |
| { return __t; } |
| |
| template < typename T > |
| class delegate; |
| |
| template < typename R, typename... Params > |
| class delegate< R(Params...) > final |
| { |
| private: |
| using CallbackType = R (*)(void*, Params...); |
| |
| using FunctionPtr = R (*)(Params...); |
| |
| template < typename Object > |
| using MethodPtr = R (Object::*)(Params...); |
| |
| template < typename Object > |
| using ConstMethodPtr = R (Object::*)(Params...) const; |
| |
| void* obj_; |
| CallbackType cb_; |
| |
| template < typename Object, MethodPtr< Object > Mptr > |
| constexpr static R invoke_method(void* obj, Params... params) noexcept( |
| noexcept((static_cast< Object* >(obj)->*Mptr)(params...))) |
| { |
| return (static_cast< Object* >(obj)->*Mptr)(params...); |
| } |
| |
| template < typename Object, ConstMethodPtr< Object > Mptr > |
| constexpr static R invoke_method(void* obj, Params... params) noexcept( |
| noexcept((static_cast< Object* >(obj)->*Mptr)(params...))) |
| { |
| return (static_cast< Object* >(obj)->*Mptr)(params...); |
| } |
| |
| template < FunctionPtr Fptr > |
| constexpr static R invoke_function(void*, Params... params) noexcept( |
| noexcept((*Fptr)(params...))) |
| { |
| return (*Fptr)(params...); |
| } |
| |
| constexpr delegate(void* obj, CallbackType callback) noexcept : obj_(obj), |
| cb_(callback) |
| { |
| } |
| |
| constexpr static R error_function(Params...) |
| { |
| while(1); |
| } |
| |
| public: |
| using base_type = delegate< R(Params...) >; |
| |
| delegate() |
| { |
| *this = from< error_function >(); |
| } |
| |
| delegate(const base_type&) = default; |
| delegate(base_type&&) = default; |
| |
| base_type& operator=(const base_type&) = default; |
| base_type& operator=(base_type&&) = default; |
| |
| template < typename Object, MethodPtr< Object > Mptr > |
| constexpr static auto from(Object& obj) noexcept |
| { |
| return delegate(&obj, &invoke_method< Object, Mptr >); |
| } |
| |
| template < typename Object, ConstMethodPtr< Object > Mptr > |
| constexpr static auto from(Object& obj) noexcept |
| { |
| return delegate(&obj, &invoke_method< Object, Mptr >); |
| } |
| |
| template < FunctionPtr Fptr > |
| constexpr static auto from() noexcept |
| { |
| static_assert(Fptr != nullptr, "Function pointer must not be null"); |
| |
| return delegate(nullptr, &invoke_function< Fptr >); |
| } |
| |
| template < typename... Args > |
| constexpr auto operator()(Args&&... params) const |
| noexcept(noexcept((*cb_)(obj_, forward< Args >(params)...))) |
| { |
| return (*cb_)(obj_, forward< Args >(params)...); |
| } |
| |
| constexpr bool valid() const noexcept |
| { |
| return (cb_ != &invoke_function< error_function >); |
| } |
| |
| constexpr bool operator==(const delegate& other) const noexcept |
| { |
| return (obj_ == other.obj_) && (cb_ == other.cb_); |
| } |
| |
| constexpr bool operator!=(const delegate& other) const noexcept |
| { |
| return (obj_ != other.obj_) || (cb_ != other.cb_); |
| } |
| }; |
| |
| delegate< void(void) > a; |
| |
| void test() |
| { |
| a(); |
| } |