dlib C++ Library - tuple.h

// 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_

AltStyle によって変換されたページ (->オリジナル) /