Skip to content
Snippets Groups Projects
Commit b801f71b authored by Jan Trávníček's avatar Jan Trávníček
Browse files

introduce ptr_tuple

parent 4b0df977
No related branches found
No related tags found
No related merge requests found
#include <extensions/ptr_tuple.hpp>
/*
* ptr_tuple.hpp
*
* Created on: Feb 28, 2014
* Author: Jan Travnicek
*/
#ifndef __PTR_TUPLE_HPP_
#define __PTR_TUPLE_HPP_
#include <ostream>
#include <sstream>
#include <string>
#include "tuple.hpp"
#include "compare.hpp"
#include "iterator.hpp"
#include "clone.hpp"
namespace ext {
template < class ... Types >
class ptr_tuple {
std::tuple < Types * ... > m_data;
template < std::size_t ... Indices >
void copyCons ( std::index_sequence < Indices ... >, const ptr_tuple & tpl ) {
( void ) std::initializer_list < int > { ( std::get < Indices > ( m_data ) = ext::clone ( std::get < Indices > ( * tpl.m_data ) ), 0 ) ... };
}
template < std::size_t ... Indices >
void moveCons ( std::index_sequence < Indices ... >, ptr_tuple && tpl ) {
( void ) std::initializer_list < int > { ( std::swap ( std::get < Indices > ( m_data ), std::get < Indices > ( tpl.m_data ) ), 0 ) ... };
}
template < std::size_t ... Indices >
void cons ( std::index_sequence < Indices ... >, const Types & ... elems ) {
( void ) std::initializer_list < int > { ( std::get < Indices > ( m_data ) = ext::clone ( elems ), 0 ) ... };
}
template < std::size_t ... Indices, class ... UTypes >
void cons ( std::index_sequence < Indices ... >, UTypes && ... elems ) {
( void ) std::initializer_list < int > { ( std::get < Indices > ( m_data ) = ext::clone ( std::forward < UTypes > ( elems ) ), 0 ) ... };
}
template < std::size_t ... Indices >
void des ( std::index_sequence < Indices ... > ) {
( void ) std::initializer_list < int > { ( delete std::get < Indices > ( m_data ), 0 ) ... };
}
public:
ptr_tuple ( const ptr_tuple & tpl ) {
copyCons ( std::make_index_sequence < sizeof ... ( Types ) > ( ), tpl );
}
ptr_tuple ( ptr_tuple && tpl ) {
moveCons ( std::make_index_sequence < sizeof ... ( Types ) > ( ), std::move ( tpl ) );
}
/* template < class ... UTypes>
ptr_tuple ( const ptr_tuple < UTypes ... > & tpl ) {
}
template < class ... UTypes >
ptr_tuple ( ptr_tuple < UTypes ... > && tpl ) {
}*/
explicit ptr_tuple ( const Types & ... elems ) {
cons ( std::make_index_sequence < sizeof ... ( Types ) > ( ), elems ... );
}
template < class ... UTypes >
explicit ptr_tuple ( UTypes && ... elems ) {
cons ( std::make_index_sequence < sizeof ... ( Types ) > ( ), std::forward < UTypes > ( elems ) ... );
}
~ptr_tuple ( ) {
des ( std::make_index_sequence < sizeof ... ( Types ) > ( ) );
}
ptr_tuple < Types ... > & operator = ( const ptr_tuple < Types ... > & other ) {
if ( this == & other )
return * this;
des ( std::make_index_sequence < sizeof ... ( Types ) > ( ) );
copyCons ( std::make_index_sequence < sizeof ... ( Types ) > ( ), other );
return *this;
}
ptr_tuple < Types ... > & operator = ( ptr_tuple < Types ... > && other ) {
std::swap ( m_data, other.m_data );
return *this;
}
void swap ( ptr_tuple & other ) {
swap ( this->m_data, other.m_data );
}
template < std::size_t I >
auto & get ( ) & {
return * std::get < I > ( m_data );
}
template < std::size_t I >
const auto & get ( ) const & {
return * std::get < I > ( m_data );
}
template < std::size_t I >
auto && get ( ) && {
return std::move ( * std::get < I > ( m_data ) );
}
};
template< class... Ts>
std::ostream& operator<<(std::ostream& out, const ext::ptr_tuple<Ts...>& tuple) {
out << "(";
bool first = true;
auto outCallback = [ & ] ( const auto & arg0 ) {
if ( ! first ) {
out << ", ";
} else {
first = false;
}
out << arg0;
};
ext::foreach ( tuple, outCallback );
out << ")";
return out;
}
template < typename ... Ts >
struct compare < ext::ptr_tuple < Ts ... > > {
int operator ()( const ext::ptr_tuple < Ts ... > & first, const ext::ptr_tuple < Ts ... > & second ) const {
return compareTupleHelper < ext::tuple_size < ext::tuple < Ts ... > >::value - 1, ext::ptr_tuple < Ts ... > >::compHelp ( first, second );
}
};
template < class ... Ts >
std::string to_string ( const ext::ptr_tuple < Ts ... > & value ) {
std::stringstream ss;
ss << value;
return ss.str();
}
template < class T >
bool operator == ( const ptr_tuple < T > & first, const ptr_tuple < T > & second ) {
static compare < ptr_tuple < T > > comp;
return comp ( first, second ) == 0;
}
template < class T >
bool operator != ( const ptr_tuple < T > & first, const ptr_tuple < T > & second ) {
return ! ( first == second );
}
template < class T >
bool operator < ( const ptr_tuple < T > & first, const ptr_tuple < T > & second ) {
static compare < ptr_tuple < T > > comp;
return comp ( first, second ) < 0;
}
template < class T >
bool operator > ( const ptr_tuple < T > & first, const ptr_tuple < T > & second ) {
return second < first;
}
template < class T >
bool operator <= ( const ptr_tuple < T > & first, const ptr_tuple < T > & second ) {
return ! ( first > second );
}
template < class T >
bool operator >= ( const ptr_tuple < T > & first, const ptr_tuple < T > & second ) {
return ! ( first < second );
}
} /* namespace ext */
namespace std {
template < class ... Ts >
void swap ( ext::ptr_tuple < Ts ... > & first, ext::ptr_tuple < Ts ... > & second ) {
first.swap ( second );
}
template < std::size_t I, class ... Types >
auto & get ( ext::ptr_tuple < Types ... > & tpl ) {
return tpl.template get < I > ( );
}
template < std::size_t I, class ... Types >
const auto & get ( const ext::ptr_tuple < Types ... > & tpl ) {
return tpl.template get < I > ( );
}
template < std::size_t I, class ... Types >
auto && get ( ext::ptr_tuple < Types ... > && tpl ) {
return tpl.template get < I > ( );
}
} /* namespace std */
namespace ext {
template<typename... _Elements>
constexpr ptr_tuple < typename std::__decay_and_strip < _Elements >::__type... > make_ptr_tuple ( _Elements && ... __args ) {
typedef ptr_tuple < typename std::__decay_and_strip < _Elements >::__type... > __result_type;
return __result_type ( std::forward < _Elements > ( __args ) ... );
}
template < class ... Types >
class tuple_size < ext::ptr_tuple < Types ... > > : public std::integral_constant < std::size_t, sizeof...( Types ) > { };
template < std::size_t I, class... Types >
struct tuple_element < I, ext::ptr_tuple < Types... > > {
typedef typename std::tuple_element < I, std::tuple < Types ... > >::type type;
};
template < class Result, unsigned I, class Callable, class ... Types >
struct call_on_nth_helper < Result, I, ext::ptr_tuple < Types ... >, Callable > {
template < class Tuple >
static Result call_on_nth_fn ( Tuple && t, unsigned index, Callable callback ) {
if ( index == 0 )
return callback ( std::get < ext::tuple_size < Tuple >::value - I > ( std::forward < ext::ptr_tuple < Types ... > > ( t ) ) );
else
return call_on_nth_helper < Result, I - 1, ext::ptr_tuple < Types ... >, Callable >::call_on_nth_fn ( std::forward < Tuple && > ( t ), index - 1, callback );
}
};
template < class Result, class Callable, class ... Types >
struct call_on_nth_helper < Result, 0, ext::ptr_tuple < Types ... >, Callable > {
template < class Tuple >
static Result call_on_nth_fn ( Tuple &&, unsigned, Callable ) {
throw std::out_of_range ( "Not enough elements in tuple." );
}
};
template < unsigned I, class Callable, class ... Types >
struct foreach_helper < I, ext::ptr_tuple < Types ... >, Callable > {
template < class Tuple >
static void foreach_fn ( Tuple && t, Callable callback ) {
foreach_helper < I - 1, ext::ptr_tuple < Types ... >, Callable >::foreach_fn ( std::forward < Tuple && > ( t ), callback );
callback ( std::get < I - 1 > ( t ) );
}
};
template < class Callable, class ... Types >
struct foreach_helper < 0, ext::ptr_tuple < Types ... >, Callable > {
template < class Tuple >
static void foreach_fn ( Tuple &&, Callable ) {
}
};
template < class Type, int size, class ... Types >
struct PtrTupleBuilder;
template < class Type, class ... Types >
struct PtrTupleBuilder < Type, 0, Types ... > {
typedef ext::ptr_tuple < Types ... > type;
};
template < class Type, int n, class ... Types >
struct PtrTupleBuilder : public PtrTupleBuilder < Type, n - 1, Type, Types ... > {
};
} /* namespace ext */
#endif /* __PTR_TUPLE_HPP_ */
#include "PtrTupleTest.h"
#include <alib/ptr_tuple>
#include <sstream>
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PtrTupleTest, "bits" );
CPPUNIT_TEST_SUITE_REGISTRATION( PtrTupleTest );
void PtrTupleTest::setUp() {
}
void PtrTupleTest::tearDown() {
}
void PtrTupleTest::testCallOnNth() {
ext::ptr_tuple < int, int, int, int, int > t = ext::make_ptr_tuple ( 1, 2, 3, 4, 5 );
CPPUNIT_ASSERT ( ext::call_on_nth < int > ( t, 1, [] ( int i ) { return i; } ) == 2 );
std::stringstream ss;
ss << t;
std::cout << ss.str ( ) << std::endl;
CPPUNIT_ASSERT ( ss.str ( ) == "(1, 2, 3, 4, 5)" );
}
#ifndef PTR_TUPLE_TEST_H_
#define PTR_TUPLE_TEST_H_
#include <cppunit/extensions/HelperMacros.h>
class PtrTupleTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( PtrTupleTest );
CPPUNIT_TEST( testCallOnNth );
CPPUNIT_TEST_SUITE_END();
public:
void setUp();
void tearDown();
void testCallOnNth();
};
#endif // PTR_TUPLE_TEST_H_
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment