diff options
Diffstat (limited to 'ml/dlib/dlib/tuple')
-rw-r--r-- | ml/dlib/dlib/tuple/tuple.h | 410 | ||||
-rw-r--r-- | ml/dlib/dlib/tuple/tuple_abstract.h | 302 |
2 files changed, 712 insertions, 0 deletions
diff --git a/ml/dlib/dlib/tuple/tuple.h b/ml/dlib/dlib/tuple/tuple.h new file mode 100644 index 000000000..cac2b4ade --- /dev/null +++ b/ml/dlib/dlib/tuple/tuple.h @@ -0,0 +1,410 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TUPLe_H_ +#define DLIB_TUPLe_H_ + +#include "../enable_if.h" +#include "../algs.h" +#include "../serialize.h" +#include "tuple_abstract.h" + +// ---------------------------------------------------------------------------------------- + +#define DLIB_TUPLE_GLOBAL_HELPERS(N) \ + DLIB_TUPLE_GH(N##0) DLIB_TUPLE_GH(N##1) DLIB_TUPLE_GH(N##2) DLIB_TUPLE_GH(N##3) \ + DLIB_TUPLE_GH(N##4) DLIB_TUPLE_GH(N##5) DLIB_TUPLE_GH(N##6) DLIB_TUPLE_GH(N##7) + +#define DLIB_TUPLE_GH(N) DLIB_TUPLE_GET_INDEX(N) DLIB_TUPLE_GET_ITEM(N) DLIB_TUPLE_GET_HELPER_STRUCT(N) + +#define DLIB_TUPLE_MEMBER_GET(N) \ + DLIB_TUPLE_MG(N##0) DLIB_TUPLE_MG(N##1) DLIB_TUPLE_MG(N##2) DLIB_TUPLE_MG(N##3) \ + DLIB_TUPLE_MG(N##4) DLIB_TUPLE_MG(N##5) DLIB_TUPLE_MG(N##6) DLIB_TUPLE_MG(N##7) + +#define DLIB_TUPLE_GET_INDEX(N) \ + template <class Q, class T> const typename enable_if<is_same_type<typename T::type##N,Q>, long>::type get_index (const T&) {return N;} + +#define DLIB_TUPLE_GET_ITEM(N) \ + template <class Q,class T> const typename enable_if<is_same_type<typename T::type##N,Q>,Q>::type& get_item_const (const T& t) {return t.v##N;}\ + template <class Q,class T> typename enable_if<is_same_type<typename T::type##N,Q>,Q>::type& get_item ( T& t) {return t.v##N;} + + +#define DLIB_TUPLE_GET_HELPER_STRUCT(N) \ + template <class T> struct get_helper<N,T> \ + { \ + typedef typename T::type##N type; \ + static const type& get(const T& t) { return t.v##N; } \ + static type& get( T& t) { return t.v##N; } \ + }; + +#define DLIB_TUPLE_TEMPLATE_LIST(N) \ + class T##N##0 = null_type, class T##N##1 = null_type, class T##N##2 = null_type, class T##N##3 = null_type, \ + class T##N##4 = null_type, class T##N##5 = null_type, class T##N##6 = null_type, class T##N##7 = null_type + +#define DLIB_TUPLE_VARIABLE_LIST(N) \ + T##N##0 v##N##0; T##N##1 v##N##1; T##N##2 v##N##2; T##N##3 v##N##3; \ + T##N##4 v##N##4; T##N##5 v##N##5; T##N##6 v##N##6; T##N##7 v##N##7; \ + typedef T##N##0 type##N##0; typedef T##N##1 type##N##1; typedef T##N##2 type##N##2; \ + typedef T##N##3 type##N##3; typedef T##N##4 type##N##4; typedef T##N##5 type##N##5; \ + typedef T##N##6 type##N##6; typedef T##N##7 type##N##7; + +// ---------------------------------------------------------------------------------------- + +namespace dlib +{ + + struct null_type{}; + + // provide default serialization for the null_type + inline void serialize ( + const null_type& , + std::ostream& + ){} + inline void deserialize ( + null_type& , + std::istream& + ){} + +// ---------------------------------------------------------------------------------------- + + namespace tuple_helpers + { + template <long idx, class T> struct get_helper; + + // use these preprocessor macros to declare all the global stuff used by the + // tuple member functions. + DLIB_TUPLE_GLOBAL_HELPERS(0) + DLIB_TUPLE_GLOBAL_HELPERS(01) + DLIB_TUPLE_GLOBAL_HELPERS(02) + DLIB_TUPLE_GLOBAL_HELPERS(03) + + // ------------------------------------------------------------------------------------ + + // use templates to recursively enumerate everything in the tuple that isn't a null_type + template < + typename T, + typename F, + long i = 0, + typename enabled = void + > + struct for_each + { + static void go( + T& a, + F& funct + ) + { + funct(a.template get<i>()); + for_each<T,F,i+1>::go(a,funct); + } + + static bool go( + T& a, + F& funct, + long idx + ) + /*! + ensures + - returns true if the function was applied to the given index + - returns false if the index is invalid so the function wasn't + applied to anything + !*/ + { + if (idx == i) + { + funct(a.template get<i>()); + return true; + } + else + { + return for_each<T,F,i+1>::go(a,funct,idx); + } + } + }; + + template <bool v1, bool v2> struct template_or { const static bool value = true; }; + template <> struct template_or<false,false> { const static bool value = false; }; + + // the base case of the recursion + template < + typename T, + typename F, + long i + > + struct for_each<T,F,i,typename enable_if<template_or<i == T::max_fields , is_same_type<null_type,typename T::template get_type<i>::type >::value> >::type > + { + static void go( T&, F& ) { } + static bool go( T&, F&, long ) { return false; } + }; + + // ------------------------------------------------------------------------------------ + + // use templates to recursively enumerate everything in the tuple that isn't a null_type + template < + typename T, + long i = 0, + typename enabled = void + > + struct tuple_swap + { + static void go( + T& a, + T& b + ) + { + exchange(a.template get<i>(), b.template get<i>()); + tuple_swap<T,i+1>::go(a,b); + } + }; + + template <typename T, long i> + struct at_base_case + { + + }; + + // the base case of the recursion + template < + typename T, + long i + > + struct tuple_swap<T,i,typename enable_if<template_or<i == T::max_fields, is_same_type<null_type,typename T::template get_type<i>::type >::value > >::type > + { static void go( T&, T& ) { } }; + + // ------------------------------------------------------------------------------------ + + struct tuple_serialize + { + tuple_serialize (std::ostream& out_) : out(out_){} + std::ostream& out; + + template <typename T> + void operator() ( + T& a + ) const { serialize(a,out); } + }; + + // ------------------------------------------------------------------------------------ + + struct tuple_deserialize + { + tuple_deserialize (std::istream& in_) : in(in_){} + std::istream& in; + template <typename T> + void operator() ( + T& a + ) const { deserialize(a,in); } + }; + + + } + +// ---------------------------------------------------------------------------------------- + + // use these preprocessor macros to declare 4*8 template arguments (below we count them in octal) + template < + DLIB_TUPLE_TEMPLATE_LIST(0), // args 00-07 + DLIB_TUPLE_TEMPLATE_LIST(01), // args 010-017 + DLIB_TUPLE_TEMPLATE_LIST(02), // args 020-027 + DLIB_TUPLE_TEMPLATE_LIST(03) // args 030-037 + > + class tuple + { + public: + + // use these macros to declare 8*4 member variables + DLIB_TUPLE_VARIABLE_LIST(0) + DLIB_TUPLE_VARIABLE_LIST(01) + DLIB_TUPLE_VARIABLE_LIST(02) + DLIB_TUPLE_VARIABLE_LIST(03) + + const static long max_fields = 4*8; + + template < long idx > + struct get_type + { + typedef typename tuple_helpers::get_helper<idx,tuple>::type type; + }; + + template < long idx > + const typename tuple_helpers::get_helper<idx,tuple>::type& get ( + ) const { return tuple_helpers::get_helper<idx,tuple>::get(*this); } + + template < long idx > + typename tuple_helpers::get_helper<idx,tuple>::type& get ( + ) { return tuple_helpers::get_helper<idx,tuple>::get(*this); } + + template < class Q> + long index ( + ) const { return tuple_helpers::get_index<Q>(*this); } + + template <class Q> + const Q& get ( + ) const {return tuple_helpers::get_item_const<Q>(*this);} + + template <class Q> + Q& get ( + ) {return tuple_helpers::get_item<Q>(*this);} + + + + + template <typename F> + void for_index ( + F& funct, + long idx + ) + { + // do this #ifdef stuff to avoid getting a warning about valid_idx not being + // used when ENABLE_ASSERTS isn't defined. +#ifdef ENABLE_ASSERTS + const bool valid_idx = tuple_helpers::for_each<tuple,F>::go(*this,funct,idx); +#else + tuple_helpers::for_each<tuple,F>::go(*this,funct,idx); +#endif + DLIB_ASSERT(valid_idx, + "\tvoid tuple::for_index()" + << "\n\tYou have attempted to call for_index() with an index out of the valid range" + << "\n\tidx: " << idx + << "\n\tthis: " << this + ); + } + + template <typename F> + void for_index ( + F& funct, + long idx + ) const + { + // do this #ifdef stuff to avoid getting a warning about valid_idx not being + // used when ENABLE_ASSERTS isn't defined. +#ifdef ENABLE_ASSERTS + const bool valid_idx = tuple_helpers::for_each<const tuple,F>::go(*this,funct,idx); +#else + tuple_helpers::for_each<const tuple,F>::go(*this,funct,idx); +#endif + DLIB_ASSERT(valid_idx, + "\tvoid tuple::for_index()" + << "\n\tYou have attempted to call for_index() with an index out of the valid range" + << "\n\tidx: " << idx + << "\n\tthis: " << this + ); + } + + template <typename F> + void for_index ( + const F& funct, + long idx + ) + { + // do this #ifdef stuff to avoid getting a warning about valid_idx not being + // used when ENABLE_ASSERTS isn't defined. +#ifdef ENABLE_ASSERTS + const bool valid_idx = tuple_helpers::for_each<tuple,const F>::go(*this,funct,idx); +#else + tuple_helpers::for_each<tuple,const F>::go(*this,funct,idx); +#endif + DLIB_ASSERT(valid_idx, + "\tvoid tuple::for_index()" + << "\n\tYou have attempted to call for_index() with an index out of the valid range" + << "\n\tidx: " << idx + << "\n\tthis: " << this + ); + } + + template <typename F> + void for_index ( + const F& funct, + long idx + ) const + { + // do this #ifdef stuff to avoid getting a warning about valid_idx not being + // used when ENABLE_ASSERTS isn't defined. +#ifdef ENABLE_ASSERTS + const bool valid_idx = tuple_helpers::for_each<const tuple,const F>::go(*this,funct,idx); +#else + tuple_helpers::for_each<const tuple,const F>::go(*this,funct,idx); +#endif + DLIB_ASSERT(valid_idx, + "\tvoid tuple::for_index()" + << "\n\tYou have attempted to call for_index() with an index out of the valid range" + << "\n\tidx: " << idx + << "\n\tthis: " << this + ); + } + + + + + template <typename F> + void for_each ( + F& funct + ) { tuple_helpers::for_each<tuple,F>::go(*this,funct); } + + template <typename F> + void for_each ( + F& funct + ) const { tuple_helpers::for_each<const tuple,F>::go(*this,funct); } + + template <typename F> + void for_each ( + const F& funct + ) const { tuple_helpers::for_each<const tuple,const F>::go(*this,funct); } + + template <typename F> + void for_each ( + const F& funct + ) { tuple_helpers::for_each<tuple,const F>::go(*this,funct); } + + + + + inline friend void serialize ( + tuple& item, + std::ostream& out + ) + { + try + { + item.for_each(tuple_helpers::tuple_serialize(out)); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing an object of type dlib::tuple<>"); + } + } + + inline friend void deserialize ( + tuple& item, + std::istream& in + ) + { + try + { + item.for_each(tuple_helpers::tuple_deserialize(in)); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing an object of type dlib::tuple<>"); + } + } + + inline friend void swap ( + tuple& a, + tuple& b + ) + { + tuple_helpers::tuple_swap<tuple>::go(a,b); + } + + inline void swap( + tuple& item + ) { tuple_helpers::tuple_swap<tuple>::go(item,*this); } + + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_TUPLe_H_ + diff --git a/ml/dlib/dlib/tuple/tuple_abstract.h b/ml/dlib/dlib/tuple/tuple_abstract.h new file mode 100644 index 000000000..aff9b8122 --- /dev/null +++ b/ml/dlib/dlib/tuple/tuple_abstract.h @@ -0,0 +1,302 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_TUPLe_ABSTRACT_H_ +#ifdef DLIB_TUPLe_ABSTRACT_H_ + +#include "../algs.h" +#include "../serialize.h" +#include "tuple_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + struct null_type + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is the default type used as the default + template argument to the tuple object's template arguments. + + Also note that it has no state associated with it. + !*/ + }; + + inline void serialize ( + const null_type& , + std::ostream& + ){} + inline void deserialize ( + null_type& , + std::istream& + ){} + /*! + Serialization support is provided for null_type because in some cases + it makes your code a little more concise and easier to deal with + when using tuple objects and serialization. The serialization literally + does nothing though. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T0 = null_type, + typename T1 = null_type, + typename T2 = null_type, + typename T3 = null_type, + ... + typename T31 = null_type + > + class tuple + { + /*! + INITIAL VALUE + Each object in the tuple is default initialized by its own constructor. + The tuple object itself does not modify them or add any additional + state. + + WHAT THIS OBJECT REPRESENTS + This object represents a container of between 0 and 31 objects + where the objects contained are specified in the template + arguments. + + EXAMPLE + We can declare a tuple that contains an int, a float, and a char like so: + tuple<int,float,char> ex; + + Then we can access each of these by their index number. The index number + is just the order each type has in the template argument list. So we have: + ex.get<0>() = 5; // assign the int the value 5 + ex.get<1>() = 3.14; // assign the float the value 3.14 + ex.get<2>() = 'c'; // assign the char the value 'c' + + Also, since we only have one of each type in this example tuple we can + unambiguously access each field in the tuple by their types. So for + example, we can use this syntax to access our fields: + ex.get<int>() // returns 5 + ex.get<float>() // returns 3.14 + ex.get<char>() // returns 'c' + + We can also get the indexes of each of these fields like so: + ex.index<int>() // returns 0 + ex.index<float>() // returns 1 + ex.index<char>() // returns 2 + !*/ + + public: + // the maximum number of items this tuple template can contain + const static long max_fields = 32; + + template <long index> + struct get_type + { + typedef (the type of the Tindex template argument) type; + }; + + template <long index> + const get_type<index>::type& get ( + ) const; + /*! + requires + - 0 <= index <= 31 + ensures + - returns a const reference to the index(th) object contained + inside this tuple + !*/ + + template <long index> + get_type<index>::type& get ( + ); + /*! + requires + - 0 <= index <= 31 + ensures + - returns a non-const reference to the index(th) object contained + inside this tuple + !*/ + + template <typename Q> + const long index ( + ) const; + /*! + requires + - Q is a type of object contained in this tuple and there is + only one object of that type in the tuple + ensures + - returns the index of the object in this tuple with type Q + !*/ + + template <typename Q> + const Q& get ( + ) const; + /*! + requires + - Q is a type of object contained in this tuple and there is + only one object of that type in the tuple + ensures + - returns a const reference to the object in this tuple + with type Q + !*/ + + template <typename Q> + Q& get ( + ); + /*! + requires + - Q is a type of object contained in this tuple and there is + only one object of that type in the tuple + ensures + - returns a non-const reference to the object in this tuple + with type Q + !*/ + + template <typename F> + void for_each ( + F& funct + ); + /*! + requires + - funct is a templated function object + ensures + - for each item X in this tuple that isn't a null_type object: + - calls funct(X); + !*/ + + template <typename F> + void for_each ( + F& funct + ) const; + /*! + requires + - funct is a templated function object + ensures + - for each item X in this tuple that isn't a null_type object: + - calls funct(X); + !*/ + + template <typename F> + void for_each ( + const F& funct + ); + /*! + requires + - funct is a templated function object + ensures + - for each item X in this tuple that isn't a null_type object: + - calls funct(X); + !*/ + + template <typename F> + void for_each ( + const F& funct + ) const; + /*! + requires + - funct is a templated function object + ensures + - for each item X in this tuple that isn't a null_type object: + - calls funct(X); + !*/ + + template <typename F> + void for_index ( + F& funct, + long idx + ); + /*! + requires + - funct is a templated function object + - 0 <= idx < max_fields && get_type<idx>::type != null_type + (i.e. idx must be the index of a non-null_type object in this tuple) + ensures + - calls funct(this->get<idx>()); + !*/ + + template <typename F> + void for_index ( + F& funct, + long idx + ) const; + /*! + requires + - funct is a templated function object + - 0 <= idx < max_fields && get_type<idx>::type != null_type + (i.e. idx must be the index of a non-null_type object in this tuple) + ensures + - calls funct(this->get<idx>()); + !*/ + + template <typename F> + void for_index ( + const F& funct, + long idx + ); + /*! + requires + - funct is a templated function object + - 0 <= idx < max_fields && get_type<idx>::type != null_type + (i.e. idx must be the index of a non-null_type object in this tuple) + ensures + - calls funct(this->get<idx>()); + !*/ + + template <typename F> + void for_index ( + const F& funct, + long idx + ) const; + /*! + requires + - funct is a templated function object + - 0 <= idx < max_fields && get_type<idx>::type != null_type + (i.e. idx must be the index of a non-null_type object in this tuple) + ensures + - calls funct(this->get<idx>()); + !*/ + + void swap ( + tuple& item + ); + /*! + ensures + - swaps *this and item + !*/ + + // ------------------------------------------------- + // global functions for tuple objects + // ------------------------------------------------- + + friend void swap ( + tuple& a, + tuple& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + friend void serialize ( + const tuple& item, + std::ostream& out + ); + /*! + provides serialization support + !*/ + + friend void deserialize ( + tuple& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_TUPLe_ABSTRACT_H_ + + |