#include #include #include #include #include #include #include #include #include #include #include namespace with_iterator_lib { template class bidir_ptr_iterator: public boost::iterator_facade< bidir_ptr_iterator, Value, boost::bidirectional_traversal_tag> { public: bidir_ptr_iterator(){} explicit bidir_ptr_iterator(Value* ptr_):ptr(ptr_){} protected: Value& dereference()const{return *ptr;} bool equal(const bidir_ptr_iterator& x)const{return ptr==x.ptr;} void increment(){++ptr;} void decrement(){--ptr;} private: friend class boost::iterator_core_access; Value* ptr; public: typedef bidir_ptr_iterator type; BOOST_MPL_AUX_LAMBDA_SUPPORT(1, bidir_ptr_iterator, (Value)); }; } namespace with_operator_lib { template class bidir_ptr_iterator: public boost::bidirectional_iterator_helper< bidir_ptr_iterator, Value, std::ptrdiff_t, Value*, Value&> { public: bidir_ptr_iterator(){} explicit bidir_ptr_iterator(Value* ptr_):ptr(ptr_){} Value& operator*()const{return *ptr;} friend bool operator==( const bidir_ptr_iterator& x,const bidir_ptr_iterator& y) {return x.ptr==y.ptr;} bidir_ptr_iterator& operator++(){++ptr;return *this;} bidir_ptr_iterator& operator--(){--ptr;return *this;} private: Value* ptr; public: typedef bidir_ptr_iterator type; BOOST_MPL_AUX_LAMBDA_SUPPORT(1, bidir_ptr_iterator, (Value)); }; } #define BUFFER_SIZE 1024 #define ITERATIONS 10000 #define BASIC_TYPES (int)(char)(double)(short)(long) #define ADD_POINTER(r, data, T) (T*) #define POINTEES BASIC_TYPES BOOST_PP_SEQ_FOR_EACH(ADD_POINTER, _, BASIC_TYPES) #define ALL_TYPES BASIC_TYPES BOOST_PP_SEQ_FOR_EACH(ADD_POINTER, _, POINTEES) // #define REMOVE_POINTER_SPECIALIZATION(r, data, T) BOOST_TT_BROKEN_COMPILER_SPEC(T**) // BOOST_PP_SEQ_FOR_EACH(REMOVE_POINTER_SPECIALIZATION, _, BASIC_TYPES) template struct random_buffer; template inline void init(T*& x, int) { x = random_buffer::instance + rand() % BUFFER_SIZE; } template inline void init(T& x, ...) { x = static_cast(rand() % 100); } template struct random_buffer { static T* create() { typedef typename boost::remove_pointer::type pointee; using namespace std; srand(time(0)); T* x = (T*)malloc(BUFFER_SIZE * sizeof(T)); for (std::size_t i = 0; i < BUFFER_SIZE; ++i) init(x[i],0); return x; } static T* instance; }; template T* random_buffer::instance = random_buffer::create(); template inline T* accumulate(T* v, T* base, int) { return random_buffer::instance + (BUFFER_SIZE/2) + (v - base) % (BUFFER_SIZE/2); } template inline T accumulate(T v, T base, ...) { return static_cast( static_cast(v) - static_cast(base) ); } // Test iterators over T* template inline void test(T* buf0, T* buf1 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(MakeIterator)) { typedef typename boost::mpl::apply1::type iterator; T base = buf1[0]; for (int i = 0; i < ITERATIONS; ++i) { for(iterator it0(buf0),it0_end(buf0+BUFFER_SIZE),it1(buf1); it0!=it0_end; ++it0,it1++ ) { T v = *it0; *it1 = accumulate(v, base, 0); } } } #define TEST_ONE(r, MakeIterator, T) \ test(random_buffer::instance, random_buffer::instance); #define TEST_ALL(MakeIterator) BOOST_PP_SEQ_FOR_EACH(TEST_ONE, MakeIterator, ALL_TYPES) template double test_all(BOOST_EXPLICIT_TEMPLATE_TYPE(MakeIterator) ) { TEST_ALL(MakeIterator) TEST_ALL(MakeIterator) boost::timer time; TEST_ALL(MakeIterator) return time.elapsed(); } template double prevent_dead_code_elimination(BOOST_EXPLICIT_TEMPLATE_TYPE(T) ) { double x = 0; for (std::size_t i = 0; i < BUFFER_SIZE; ++i) { x += random_buffer::instance[i] - random_buffer::instance[(i+1) % BUFFER_SIZE]; } return x; } int main() { double operator_time = test_all >(); double iterator_time = test_all >(); std::cout << "with operator library: " << operator_time << std::endl; std::cout << "with iterator library: " << iterator_time << std::endl; double undead = 0; #define PREVENT_DEAD_CODE(r, data, T) undead += prevent_dead_code_elimination(); BOOST_PP_SEQ_FOR_EACH(PREVENT_DEAD_CODE, _, ALL_TYPES); return undead == .5; }