517 lines
17 KiB
C++
517 lines
17 KiB
C++
// 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 <dlib/any.h> 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<function_type>::result_type result_type;
|
|
typedef typename sig_traits<function_type>::arg1_type arg1_type;
|
|
typedef typename sig_traits<function_type>::arg2_type arg2_type;
|
|
typedef typename sig_traits<function_type>::arg3_type arg3_type;
|
|
typedef typename sig_traits<function_type>::arg4_type arg4_type;
|
|
typedef typename sig_traits<function_type>::arg5_type arg5_type;
|
|
typedef typename sig_traits<function_type>::arg6_type arg6_type;
|
|
typedef typename sig_traits<function_type>::arg7_type arg7_type;
|
|
typedef typename sig_traits<function_type>::arg8_type arg8_type;
|
|
typedef typename sig_traits<function_type>::arg9_type arg9_type;
|
|
typedef typename sig_traits<function_type>::arg10_type arg10_type;
|
|
const static unsigned long num_args = sig_traits<function_type>::num_args;
|
|
|
|
any_function()
|
|
{
|
|
}
|
|
|
|
any_function (
|
|
const any_function& item
|
|
)
|
|
{
|
|
if (item.data)
|
|
{
|
|
item.data->copy_to(data);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
any_function (
|
|
const T& item
|
|
)
|
|
{
|
|
typedef typename basic_type<T>::type U;
|
|
data.reset(new derived<U,function_type>(item));
|
|
}
|
|
|
|
void clear (
|
|
)
|
|
{
|
|
data.reset();
|
|
}
|
|
|
|
template <typename T>
|
|
bool contains (
|
|
) const
|
|
{
|
|
typedef typename basic_type<T>::type U;
|
|
return dynamic_cast<derived<U,function_type>*>(data.get()) != 0;
|
|
}
|
|
|
|
bool is_empty(
|
|
) const
|
|
{
|
|
return data.get() == 0;
|
|
}
|
|
|
|
bool is_set(
|
|
) const
|
|
{
|
|
return !is_empty();
|
|
}
|
|
|
|
template <typename T>
|
|
T& cast_to(
|
|
)
|
|
{
|
|
typedef typename basic_type<T>::type U;
|
|
derived<U,function_type>* d = dynamic_cast<derived<U,function_type>*>(data.get());
|
|
if (d == 0)
|
|
{
|
|
throw bad_any_cast();
|
|
}
|
|
|
|
return d->item;
|
|
}
|
|
|
|
template <typename T>
|
|
const T& cast_to(
|
|
) const
|
|
{
|
|
typedef typename basic_type<T>::type U;
|
|
derived<U,function_type>* d = dynamic_cast<derived<U,function_type>*>(data.get());
|
|
if (d == 0)
|
|
{
|
|
throw bad_any_cast();
|
|
}
|
|
|
|
return d->item;
|
|
}
|
|
|
|
template <typename T>
|
|
T& get(
|
|
)
|
|
{
|
|
typedef typename basic_type<T>::type U;
|
|
derived<U,function_type>* d = dynamic_cast<derived<U,function_type>*>(data.get());
|
|
if (d == 0)
|
|
{
|
|
d = new derived<U,function_type>();
|
|
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 <typename FT>
|
|
struct Tbase
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual result_type evaluate () const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
typename A1
|
|
>
|
|
struct Tbase<T (A1)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate ( A1) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
typename A1, typename A2
|
|
>
|
|
struct Tbase<T (A1,A2)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate (A1,A2) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
typename A1, typename A2, typename A3
|
|
>
|
|
struct Tbase<T (A1,A2,A3)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate (A1,A2,A3) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
typename A1, typename A2, typename A3,
|
|
typename A4
|
|
>
|
|
struct Tbase<T (A1,A2,A3,A4)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate (A1,A2,A3,A4) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
typename A1, typename A2, typename A3,
|
|
typename A4, typename A5
|
|
>
|
|
struct Tbase<T (A1,A2,A3,A4,A5)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate (A1,A2,A3,A4,A5) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
typename A1, typename A2, typename A3,
|
|
typename A4, typename A5, typename A6
|
|
>
|
|
struct Tbase<T (A1,A2,A3,A4,A5,A6)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate (A1,A2,A3,A4,A5,A6) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
typename A1, typename A2, typename A3,
|
|
typename A4, typename A5, typename A6,
|
|
typename A7
|
|
>
|
|
struct Tbase<T (A1,A2,A3,A4,A5,A6,A7)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate (A1,A2,A3,A4,A5,A6,A7) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
typename A1, typename A2, typename A3,
|
|
typename A4, typename A5, typename A6,
|
|
typename A7, typename A8
|
|
>
|
|
struct Tbase<T (A1,A2,A3,A4,A5,A6,A7,A8)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate (A1,A2,A3,A4,A5,A6,A7,A8) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& 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<T (A1,A2,A3,A4,A5,A6,A7,A8,A9)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate (A1,A2,A3,A4,A5,A6,A7,A8,A9) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& 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<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10)>
|
|
{
|
|
virtual ~Tbase() {}
|
|
virtual T evaluate (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10) const = 0;
|
|
virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
|
|
};
|
|
|
|
typedef Tbase<function_type> 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 <typename T, typename enabled = void>
|
|
struct funct_type { typedef T type; };
|
|
template <typename T>
|
|
struct funct_type<T, typename enable_if<is_function<T> >::type> { typedef T* type; };
|
|
|
|
template <typename T>
|
|
static typename enable_if<is_function<T>,const T*>::type copy (const T& item) { return &item; }
|
|
template <typename T>
|
|
static typename disable_if<is_function<T>,const T&>::type copy (const T& item) { return item; }
|
|
|
|
template <typename T, typename U>
|
|
static typename enable_if<is_function<T>,const T&>::type deref (const U& item) { return *item; }
|
|
template <typename T, typename U>
|
|
static typename disable_if<is_function<T>,const T&>::type deref (const U& item) { return item; }
|
|
|
|
// -----------------------------------------------
|
|
|
|
#define DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE \
|
|
typename funct_type<T>::type item; \
|
|
derived() {} \
|
|
derived(const T& val) : item(copy(val)) {} \
|
|
virtual void copy_to ( std::unique_ptr<base>& dest) const \
|
|
{ dest.reset(new derived(deref<T>(item))); }
|
|
|
|
template <typename T, typename FT>
|
|
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 <typename T, typename A1>
|
|
struct derived<T,result_type (A1)> : 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 <typename T, typename A1, typename A2>
|
|
struct derived<T,result_type (A1,A2)> : 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 <typename T, typename A1, typename A2, typename A3>
|
|
struct derived<T,result_type (A1,A2,A3)> : 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 <typename T, typename A1, typename A2, typename A3,
|
|
typename A4>
|
|
struct derived<T,result_type (A1,A2,A3,A4)> : 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 <typename T, typename A1, typename A2, typename A3,
|
|
typename A4, typename A5>
|
|
struct derived<T,result_type (A1,A2,A3,A4,A5)> : 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 <typename T, typename A1, typename A2, typename A3,
|
|
typename A4, typename A5, typename A6>
|
|
struct derived<T,result_type (A1,A2,A3,A4,A5,A6)> : 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 <typename T, typename A1, typename A2, typename A3,
|
|
typename A4, typename A5, typename A6,
|
|
typename A7>
|
|
struct derived<T,result_type (A1,A2,A3,A4,A5,A6,A7)> : 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 <typename T, typename A1, typename A2, typename A3,
|
|
typename A4, typename A5, typename A6,
|
|
typename A7, typename A8>
|
|
struct derived<T,result_type (A1,A2,A3,A4,A5,A6,A7,A8)> : 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 <typename T, typename A1, typename A2, typename A3,
|
|
typename A4, typename A5, typename A6,
|
|
typename A7, typename A8, typename A9>
|
|
struct derived<T,result_type (A1,A2,A3,A4,A5,A6,A7,A8,A9)> : 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 <typename T, typename A1, typename A2, typename A3,
|
|
typename A4, typename A5, typename A6,
|
|
typename A7, typename A8, typename A9,
|
|
typename A10>
|
|
struct derived<T,result_type (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10)> : 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<base> data;
|
|
|
|
#undef DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
|
|
|
|
#endif // DLIB_ANY_FUNCTION_RETURN
|
|
|