// Copyright (C) 2011 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_ANY_FUNCTION_RETURN #error "You aren't supposed to directly #include this file. #include instead." #endif #ifdef _MSC_VER // When using visual studio 2012, disable the warning "warning C4180: qualifier applied to function type has no meaning; ignored" // that you get about some template expansions applying & to function types. #pragma warning(disable : 4180) #endif #ifdef DLIB_ANY_FUNCTION_RETURN // This file contains the body of the any_function class. We use the // preprocessor to generate many different versions. There are // versions which return a value and those which return void. For // each of these types there are versions with differing numbers // of arguments. public: typedef typename sig_traits::result_type result_type; typedef typename sig_traits::arg1_type arg1_type; typedef typename sig_traits::arg2_type arg2_type; typedef typename sig_traits::arg3_type arg3_type; typedef typename sig_traits::arg4_type arg4_type; typedef typename sig_traits::arg5_type arg5_type; typedef typename sig_traits::arg6_type arg6_type; typedef typename sig_traits::arg7_type arg7_type; typedef typename sig_traits::arg8_type arg8_type; typedef typename sig_traits::arg9_type arg9_type; typedef typename sig_traits::arg10_type arg10_type; const static unsigned long num_args = sig_traits::num_args; any_function() { } any_function ( const any_function& item ) { if (item.data) { item.data->copy_to(data); } } template any_function ( const T& item ) { typedef typename basic_type::type U; data.reset(new derived(item)); } void clear ( ) { data.reset(); } template bool contains ( ) const { typedef typename basic_type::type U; return dynamic_cast*>(data.get()) != 0; } bool is_empty( ) const { return data.get() == 0; } bool is_set( ) const { return !is_empty(); } template T& cast_to( ) { typedef typename basic_type::type U; derived* d = dynamic_cast*>(data.get()); if (d == 0) { throw bad_any_cast(); } return d->item; } template const T& cast_to( ) const { typedef typename basic_type::type U; derived* d = dynamic_cast*>(data.get()); if (d == 0) { throw bad_any_cast(); } return d->item; } template T& get( ) { typedef typename basic_type::type U; derived* d = dynamic_cast*>(data.get()); if (d == 0) { d = new derived(); data.reset(d); } return d->item; } any_function& operator= ( const any_function& item ) { any_function(item).swap(*this); return *this; } void swap ( any_function& item ) { data.swap(item.data); } result_type operator()(DLIB_ANY_FUNCTION_ARG_LIST) const { validate(); DLIB_ANY_FUNCTION_RETURN data->evaluate(DLIB_ANY_FUNCTION_ARGS); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to call a dlib::any_function but you have supplied arguments which don't match the function signature used by the dlib::any_function. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ private: void validate () const { // make sure requires clause is not broken DLIB_ASSERT(is_empty() == false, "\t result_type any_function::operator()" << "\n\t You can't call operator() on an empty any_function" << "\n\t this: " << this ); } template struct Tbase { virtual ~Tbase() {} virtual result_type evaluate () const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1 > struct Tbase { virtual ~Tbase() {} virtual T evaluate ( A1) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1, typename A2 > struct Tbase { virtual ~Tbase() {} virtual T evaluate (A1,A2) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1, typename A2, typename A3 > struct Tbase { virtual ~Tbase() {} virtual T evaluate (A1,A2,A3) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1, typename A2, typename A3, typename A4 > struct Tbase { virtual ~Tbase() {} virtual T evaluate (A1,A2,A3,A4) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1, typename A2, typename A3, typename A4, typename A5 > struct Tbase { virtual ~Tbase() {} virtual T evaluate (A1,A2,A3,A4,A5) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6 > struct Tbase { virtual ~Tbase() {} virtual T evaluate (A1,A2,A3,A4,A5,A6) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7 > struct Tbase { virtual ~Tbase() {} virtual T evaluate (A1,A2,A3,A4,A5,A6,A7) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8 > struct Tbase { virtual ~Tbase() {} virtual T evaluate (A1,A2,A3,A4,A5,A6,A7,A8) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9 > struct Tbase { virtual ~Tbase() {} virtual T evaluate (A1,A2,A3,A4,A5,A6,A7,A8,A9) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; template < typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10 > struct Tbase { virtual ~Tbase() {} virtual T evaluate (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10) const = 0; virtual void copy_to ( std::unique_ptr& dest) const = 0; }; typedef Tbase base; // ----------------------------------------------- // Some templates to help deal with the weirdness of storing C function types (rather than pointer to functions). // Basically, we make sure things always get turned into function pointers even if the user gives a function reference. template struct funct_type { typedef T type; }; template struct funct_type >::type> { typedef T* type; }; template static typename enable_if,const T*>::type copy (const T& item) { return &item; } template static typename disable_if,const T&>::type copy (const T& item) { return item; } template static typename enable_if,const T&>::type deref (const U& item) { return *item; } template static typename disable_if,const T&>::type deref (const U& item) { return item; } // ----------------------------------------------- #define DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE \ typename funct_type::type item; \ derived() {} \ derived(const T& val) : item(copy(val)) {} \ virtual void copy_to ( std::unique_ptr& dest) const \ { dest.reset(new derived(deref(item))); } template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( ) const { DLIB_ANY_FUNCTION_RETURN item(); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1 ) const { DLIB_ANY_FUNCTION_RETURN item(a1); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1, A2 a2 ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1, A2 a2, A3 a3 ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1, A2 a2, A3 a3, A4 a4 ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6 ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7 ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6,a7); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8 ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6,a7,a8); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9 ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6,a7,a8,a9); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; template struct derived : public base { DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE virtual result_type evaluate ( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10 ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); } /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! If you are getting an error on the above line then it means you have attempted to assign a function or function object to a dlib::any_function but the signatures of the source and destination functions don't match. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ }; std::unique_ptr data; #undef DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE #endif // DLIB_ANY_FUNCTION_RETURN