summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/tuple
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/tuple')
-rw-r--r--ml/dlib/dlib/tuple/tuple.h410
-rw-r--r--ml/dlib/dlib/tuple/tuple_abstract.h302
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_
+
+