1 /* 2 * Copyright Andrey Semashev 2007 - 2015. 3 * Distributed under the Boost Software License, Version 1.0. 4 * (See accompanying file LICENSE_1_0.txt or copy at 5 * http://www.boost.org/LICENSE_1_0.txt) 6 */ 7 8 template< 9 typename ResultT 10 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename ArgT) 11 > 12 class light_function< ResultT (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) > 13 { 14 typedef light_function this_type; 15 BOOST_COPYABLE_AND_MOVABLE(this_type) 16 17 public: 18 typedef ResultT result_type; 19 20 private: 21 struct impl_base 22 { 23 typedef result_type (*invoke_type)(void* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT)); 24 const invoke_type invoke; 25 26 typedef impl_base* (*clone_type)(const void*); 27 const clone_type clone; 28 29 typedef void (*destroy_type)(void*); 30 const destroy_type destroy; 31 impl_baselight_function::impl_base32 impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) 33 { 34 } 35 36 BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) 37 BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) 38 }; 39 40 #if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) 41 template< typename FunT > 42 class impl; 43 template< typename FunT > 44 friend class impl; 45 #endif 46 47 template< typename FunT > 48 class impl : 49 public impl_base 50 { 51 typedef impl< FunT > this_type; 52 53 FunT m_Function; 54 55 public: impl(FunT const & fun)56 explicit impl(FunT const& fun) : 57 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), 58 m_Function(fun) 59 { 60 } 61 62 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) impl(FunT && fun)63 explicit impl(FunT&& fun) : 64 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), 65 m_Function(boost::move(fun)) 66 { 67 } 68 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 69 destroy_impl(void * self)70 static void destroy_impl(void* self) 71 { 72 delete static_cast< impl* >(static_cast< impl_base* >(self)); 73 } clone_impl(const void * self)74 static impl_base* clone_impl(const void* self) 75 { 76 return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); 77 } invoke_impl(void * self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS (BOOST_PP_ITERATION (),ArgT,arg))78 static result_type invoke_impl(void* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) 79 { 80 return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)); 81 } 82 83 BOOST_DELETED_FUNCTION(impl(impl const&)) 84 BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) 85 }; 86 87 private: 88 impl_base* m_pImpl; 89 90 public: light_function()91 BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) 92 { 93 } light_function(this_type const & that)94 light_function(this_type const& that) 95 { 96 if (that.m_pImpl) 97 m_pImpl = that.m_pImpl->clone(that.m_pImpl); 98 else 99 m_pImpl = NULL; 100 } 101 light_function(BOOST_RV_REF (this_type)that)102 light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT 103 { 104 m_pImpl = that.m_pImpl; 105 that.m_pImpl = NULL; 106 } 107 light_function(BOOST_RV_REF (const this_type)that)108 light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT 109 { 110 m_pImpl = that.m_pImpl; 111 ((this_type&)that).m_pImpl = NULL; 112 } 113 114 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 115 template< typename FunT > light_function(FunT && fun)116 light_function(FunT&& fun) : 117 m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) 118 { 119 } 120 #else 121 template< typename FunT > light_function(FunT const & fun,typename boost::disable_if_c<is_rv_or_same<FunT,this_type>::value,boost::log::aux::sfinae_dummy>::type=boost::log::aux::sfinae_dummy ())122 light_function(FunT const& fun, typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) : 123 m_pImpl(new impl< FunT >(fun)) 124 { 125 } 126 template< typename FunT > light_function(BOOST_RV_REF (FunT)fun,typename boost::disable_if_c<is_cv_same<FunT,this_type>::value,boost::log::aux::sfinae_dummy>::type=boost::log::aux::sfinae_dummy ())127 light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) : 128 m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) 129 { 130 } 131 #endif 132 133 //! Constructor from NULL 134 #if !defined(BOOST_NO_CXX11_NULLPTR) light_function(std::nullptr_t)135 BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT 136 #else 137 BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT 138 #endif 139 : m_pImpl(NULL) 140 { 141 #if defined(BOOST_NO_CXX11_NULLPTR) 142 BOOST_ASSERT(p == 0); 143 #endif 144 } ~light_function()145 ~light_function() 146 { 147 clear(); 148 } 149 operator =(BOOST_RV_REF (this_type)that)150 light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT 151 { 152 this->swap(that); 153 return *this; 154 } operator =(BOOST_COPY_ASSIGN_REF (this_type)that)155 light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) 156 { 157 light_function tmp = static_cast< this_type const& >(that); 158 this->swap(tmp); 159 return *this; 160 } 161 //! Assignment of NULL 162 #if !defined(BOOST_NO_CXX11_NULLPTR) operator =(std::nullptr_t)163 light_function& operator= (std::nullptr_t) 164 #else 165 light_function& operator= (int p) 166 #endif 167 { 168 #if defined(BOOST_NO_CXX11_NULLPTR) 169 BOOST_ASSERT(p == 0); 170 #endif 171 clear(); 172 return *this; 173 } 174 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 175 template< typename FunT > operator =(FunT && fun)176 light_function& operator= (FunT&& fun) 177 { 178 light_function tmp(boost::forward< FunT >(fun)); 179 this->swap(tmp); 180 return *this; 181 } 182 #else 183 template< typename FunT > 184 typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type operator =(FunT const & fun)185 operator= (FunT const& fun) 186 { 187 light_function tmp(fun); 188 this->swap(tmp); 189 return *this; 190 } 191 #endif 192 operator ()(BOOST_PP_ENUM_BINARY_PARAMS (BOOST_PP_ITERATION (),ArgT,arg)) const193 result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const 194 { 195 return m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg)); 196 } 197 198 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() 199 bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } empty() const200 bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } clear()201 void clear() BOOST_NOEXCEPT 202 { 203 if (m_pImpl) 204 { 205 m_pImpl->destroy(m_pImpl); 206 m_pImpl = NULL; 207 } 208 } 209 swap(this_type & that)210 void swap(this_type& that) BOOST_NOEXCEPT 211 { 212 impl_base* p = m_pImpl; 213 m_pImpl = that.m_pImpl; 214 that.m_pImpl = p; 215 } 216 }; 217 218 template< 219 BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) 220 > 221 class light_function< void (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) > 222 { 223 typedef light_function this_type; 224 BOOST_COPYABLE_AND_MOVABLE(this_type) 225 226 public: 227 typedef void result_type; 228 229 private: 230 struct impl_base 231 { 232 typedef void (*invoke_type)(void* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT)); 233 const invoke_type invoke; 234 235 typedef impl_base* (*clone_type)(const void*); 236 const clone_type clone; 237 238 typedef void (*destroy_type)(void*); 239 const destroy_type destroy; 240 impl_baselight_function::impl_base241 impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) 242 { 243 } 244 245 BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) 246 BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) 247 }; 248 249 #if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) 250 template< typename FunT > 251 class impl; 252 template< typename FunT > 253 friend class impl; 254 #endif 255 256 template< typename FunT > 257 class impl : 258 public impl_base 259 { 260 typedef impl< FunT > this_type; 261 262 FunT m_Function; 263 264 public: impl(FunT const & fun)265 explicit impl(FunT const& fun) : 266 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), 267 m_Function(fun) 268 { 269 } 270 271 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) impl(FunT && fun)272 explicit impl(FunT&& fun) : 273 impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), 274 m_Function(boost::move(fun)) 275 { 276 } 277 #endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 278 destroy_impl(void * self)279 static void destroy_impl(void* self) 280 { 281 delete static_cast< impl* >(static_cast< impl_base* >(self)); 282 } clone_impl(const void * self)283 static impl_base* clone_impl(const void* self) 284 { 285 return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); 286 } invoke_impl(void * self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS (BOOST_PP_ITERATION (),ArgT,arg))287 static result_type invoke_impl(void* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) 288 { 289 static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)); 290 } 291 292 BOOST_DELETED_FUNCTION(impl(impl const&)) 293 BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) 294 }; 295 296 private: 297 impl_base* m_pImpl; 298 299 public: light_function()300 BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) 301 { 302 } light_function(this_type const & that)303 light_function(this_type const& that) 304 { 305 if (that.m_pImpl) 306 m_pImpl = that.m_pImpl->clone(that.m_pImpl); 307 else 308 m_pImpl = NULL; 309 } light_function(BOOST_RV_REF (this_type)that)310 light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT 311 { 312 m_pImpl = that.m_pImpl; 313 that.m_pImpl = NULL; 314 } 315 light_function(BOOST_RV_REF (const this_type)that)316 light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT 317 { 318 m_pImpl = that.m_pImpl; 319 ((this_type&)that).m_pImpl = NULL; 320 } 321 322 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 323 template< typename FunT > light_function(FunT && fun)324 light_function(FunT&& fun) : 325 m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) 326 { 327 } 328 #else 329 template< typename FunT > light_function(FunT const & fun,typename boost::disable_if_c<is_rv_or_same<FunT,this_type>::value,boost::log::aux::sfinae_dummy>::type=boost::log::aux::sfinae_dummy ())330 light_function(FunT const& fun, typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) : 331 m_pImpl(new impl< FunT >(fun)) 332 { 333 } 334 template< typename FunT > light_function(BOOST_RV_REF (FunT)fun,typename boost::disable_if_c<is_cv_same<FunT,this_type>::value,boost::log::aux::sfinae_dummy>::type=boost::log::aux::sfinae_dummy ())335 light_function(BOOST_RV_REF(FunT) fun, typename boost::disable_if_c< is_cv_same< FunT, this_type >::value, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) : 336 m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) 337 { 338 } 339 #endif 340 341 //! Constructor from NULL 342 #if !defined(BOOST_NO_CXX11_NULLPTR) light_function(std::nullptr_t)343 BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT 344 #else 345 BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT 346 #endif 347 : m_pImpl(NULL) 348 { 349 #if defined(BOOST_NO_CXX11_NULLPTR) 350 BOOST_ASSERT(p == 0); 351 #endif 352 } ~light_function()353 ~light_function() 354 { 355 clear(); 356 } 357 operator =(BOOST_RV_REF (this_type)that)358 light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT 359 { 360 this->swap(that); 361 return *this; 362 } operator =(BOOST_COPY_ASSIGN_REF (this_type)that)363 light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) 364 { 365 light_function tmp = static_cast< this_type const& >(that); 366 this->swap(tmp); 367 return *this; 368 } 369 //! Assignment of NULL 370 #if !defined(BOOST_NO_CXX11_NULLPTR) operator =(std::nullptr_t)371 light_function& operator= (std::nullptr_t) 372 #else 373 light_function& operator= (int p) 374 #endif 375 { 376 #if defined(BOOST_NO_CXX11_NULLPTR) 377 BOOST_ASSERT(p == 0); 378 #endif 379 clear(); 380 return *this; 381 } 382 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) 383 template< typename FunT > operator =(FunT && fun)384 light_function& operator= (FunT&& fun) 385 { 386 light_function tmp(boost::forward< FunT >(fun)); 387 this->swap(tmp); 388 return *this; 389 } 390 #else 391 template< typename FunT > 392 typename boost::disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type operator =(FunT const & fun)393 operator= (FunT const& fun) 394 { 395 light_function tmp(fun); 396 this->swap(tmp); 397 return *this; 398 } 399 #endif 400 operator ()(BOOST_PP_ENUM_BINARY_PARAMS (BOOST_PP_ITERATION (),ArgT,arg)) const401 result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const 402 { 403 m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg)); 404 } 405 406 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() 407 bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } empty() const408 bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } clear()409 void clear() BOOST_NOEXCEPT 410 { 411 if (m_pImpl) 412 { 413 m_pImpl->destroy(m_pImpl); 414 m_pImpl = NULL; 415 } 416 } 417 swap(this_type & that)418 void swap(this_type& that) BOOST_NOEXCEPT 419 { 420 impl_base* p = m_pImpl; 421 m_pImpl = that.m_pImpl; 422 that.m_pImpl = p; 423 } 424 }; 425