2ba60a821976b48e94f866decbaa0e4539849ad6
[platform/upstream/boost.git] / libs / type_traits / examples / copy_example.cpp
1
2 /*
3  *
4  * (C) Copyright John Maddock 1999-2005. 
5  * Use, modification and distribution are subject to the 
6  * Boost Software License, Version 1.0. (See accompanying file 
7  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8  *
9  * This file provides some example of type_traits usage -
10  * by "optimising" various algorithms:
11  *
12  * opt::copy - optimised for trivial copy (cf std::copy)
13  *
14  */
15
16 #include <iostream>
17 #include <typeinfo>
18 #include <algorithm>
19 #include <iterator>
20 #include <memory>
21
22 #include <boost/test/included/prg_exec_monitor.hpp>
23 #include <boost/timer.hpp>
24 #include <boost/type_traits.hpp>
25
26 using std::cout;
27 using std::endl;
28 using std::cin;
29
30 namespace opt{
31
32 //
33 // opt::copy
34 // same semantics as std::copy
35 // calls memcpy where appropriate.
36 //
37
38 namespace detail{
39
40 template<typename I1, typename I2, bool b>
41 I2 copy_imp(I1 first, I1 last, I2 out, const boost::integral_constant<bool, b>&)
42 {
43    while(first != last)
44    {
45       *out = *first;
46       ++out;
47       ++first;
48    }
49    return out;
50 }
51
52 template<typename T>
53 T* copy_imp(const T* first, const T* last, T* out, const boost::true_type&)
54 {
55    memmove(out, first, (last-first)*sizeof(T));
56    return out+(last-first);
57 }
58
59
60 }
61
62 template<typename I1, typename I2>
63 inline I2 copy(I1 first, I1 last, I2 out)
64 {
65    //
66    // We can copy with memcpy if T has a trivial assignment operator,
67    // and if the iterator arguments are actually pointers (this last
68    // requirement we detect with overload resolution):
69    //
70    typedef typename std::iterator_traits<I1>::value_type value_type;
71    return detail::copy_imp(first, last, out, boost::has_trivial_assign<value_type>());
72 }
73
74 }   // namespace opt
75
76 namespace non_opt
77 {
78
79 template<typename I1, typename I2>
80 inline I2 copy(I1 first, I1 last, I2 out)
81 {
82    return opt::detail::copy_imp(first, last, out, boost::false_type());
83 }
84
85 }
86
87 //
88 // define some global data:
89 //
90 const int array_size = 1000;
91 int i_array_[array_size] = {0,};
92 const int ci_array_[array_size] = {0,};
93 char c_array_[array_size] = {0,};
94 const char cc_array_[array_size] = { 0,};
95 //
96 // since arrays aren't iterators we define a set of pointer
97 // aliases into the arrays (otherwise the compiler is entitled
98 // to deduce the type passed to the template functions as
99 // T (&)[N] rather than T*).
100 int* i_array = i_array_;
101 const int* ci_array = ci_array_;
102 char* c_array = c_array_;
103 const char* cc_array = cc_array_;
104
105 const int iter_count = 1000000;
106
107 int cpp_main(int argc, char* argv[])
108 {
109    boost::timer t;
110    double result;
111    int i;
112    cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl;
113    cout << "testing copy...\n"
114    "[Some standard library versions may already perform this optimisation.]" << endl;
115    
116    // cache load:
117    opt::copy(ci_array, ci_array + array_size, i_array);
118
119    // time optimised version:
120    t.restart();
121    for(i = 0; i < iter_count; ++i)
122    {
123       opt::copy(ci_array, ci_array + array_size, i_array);
124    }
125    result = t.elapsed();
126    cout << "opt::copy<const int*, int*>: " << result << endl;
127
128    // cache load:
129    non_opt::copy(ci_array, ci_array + array_size, i_array);
130
131    // time non-optimised version:
132    t.restart();
133    for(i = 0; i < iter_count; ++i)
134    {
135       non_opt::copy(ci_array, ci_array + array_size, i_array);
136    }
137    result = t.elapsed();
138    cout << "non_opt::copy<const int*, int*>: " << result << endl;
139
140    // cache load:
141    std::copy(ci_array, ci_array + array_size, i_array);
142
143    // time standard version:
144    t.restart();
145    for(i = 0; i < iter_count; ++i)
146    {
147       std::copy(ci_array, ci_array + array_size, i_array);
148    }
149    result = t.elapsed();
150    cout << "std::copy<const int*, int*>: " << result << endl;
151
152    // cache load:
153    opt::copy(cc_array, cc_array + array_size, c_array);
154
155    // time optimised version:
156    t.restart();
157    for(i = 0; i < iter_count; ++i)
158    {
159       opt::copy(cc_array, cc_array + array_size, c_array);
160    }
161    result = t.elapsed();
162    cout << "opt::copy<const char*, char*>: " << result << endl;
163
164    // cache load:
165    non_opt::copy(cc_array, cc_array + array_size, c_array);
166
167    // time optimised version:
168    t.restart();
169    for(i = 0; i < iter_count; ++i)
170    {
171       non_opt::copy(cc_array, cc_array + array_size, c_array);
172    }
173    result = t.elapsed();
174    cout << "non_opt::copy<const char*, char*>: " << result << endl;
175
176    // cache load:
177    std::copy(cc_array, cc_array + array_size, c_array);
178
179    // time standard version:
180    t.restart();
181    for(i = 0; i < iter_count; ++i)
182    {
183       std::copy(cc_array, cc_array + array_size, c_array);
184    }
185    result = t.elapsed();
186    cout << "std::copy<const char*, char*>: " << result << endl;
187
188    return 0;
189 }
190
191
192
193
194
195
196
197