#include <iostream>
#include <vector>
#include <list>
#include <cstring>
#include <iterator>
#include <type_traits>
#include <algorithm> //for std::equal
#include <cassert>
using std:: cout ;
using std:: endl ;
using std:: boolalpha ;
using std:: vector ;
using std:: list ;
using std:: equal ;
using std:: memmove ;
using std:: begin ;
using std:: end ;
using std:: distance ;
using std:: back_inserter ;
using std:: true_type ;
using std:: is_pointer ;
using std:: is_same ;
//Would prefer std::is_trivally_copyable, but libstdc++ hasn't implemented it yet.
using std:: is_literal_type ;
/*
This code demonstrates the use of tag-dispatch to internally optimize std::copy
by calling std::memcpy as an implementation detail whenever it is safe to do so.
Tag-dispatch is a technique whereby you use type traits to select a function
implementation at compile-time by leveraging overloading.
I chose to use 4 type-traits to make the determination of whether or not it is
safe. You may be able to optimize for more cases if you used more, or a different
set of, traits.
-Mark
*/
namespace mine { //Kill compiler error because of libstdc++ bug (somehow std::copy was in scope)
//Declarations:
template < typename InputIt, typename OutputIt>
OutputIt copy( InputIt in_first, InputIt in_last, OutputIt out_first) ;
namespace detail {
template < typename InputIt, typename OutputIt>
OutputIt copyImpl( InputIt in_first, InputIt in_last, OutputIt out_first,
true_type, true_type, true_type, true_type) ;
template < typename InputIt, typename OutputIt,
typename InputIsPointerTag, typename OutputIsPointerTag,
typename SameTypesTag, typename TriviallyCopyableTag>
OutputIt copyImpl( InputIt in_first, InputIt in_last, OutputIt out_first,
InputIsPointerTag, OutputIsPointerTag, SameTypesTag, TriviallyCopyableTag) ;
} //!detail
} //!mine
int main( ) {
{
int a[ ] = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
int b[ 10 ] ;
mine:: copy ( begin( a) , end( a) , begin( b) ) ;
assert ( equal( begin( a) , end( a) , begin( b) ) ) ;
}
{
vector< int > a { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
vector< int > b;
b.resize ( 10 ) ;
mine:: copy ( begin( a) , end( a) , begin( b) ) ;
assert ( equal( begin( a) , end( a) , begin( b) ) ) ;
}
{
list< int > a { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } ;
list< int > b;
mine:: copy ( begin( a) , end( a) , back_inserter( b) ) ;
assert ( equal( begin( a) , end( a) , begin( b) ) ) ;
}
return 0 ;
}
namespace mine {
template < typename InputIt, typename OutputIt>
OutputIt copy( InputIt in_first, InputIt in_last, OutputIt out_first) {
using InputElementType = decltype( * in_first) ;
using OutputElementType = decltype( * out_first) ;
cout << boolalpha
<< "\n Input iterator is pointer:\t "
<< is_pointer< InputIt> :: value << '\n '
<< "Output iterator is pointer:\t "
<< is_pointer< OutputIt> :: value << '\n '
<< "Input and output iterators deref to the same type:\t "
<< is_same< InputElementType, OutputElementType> :: value << '\n '
<< "Element is trivially copyable:\t "
<< is_literal_type< InputElementType> :: value << '\n ' << endl;
//Use tag-dispatch technique to select the right implementation function.
//The objects we create for tag dispatch will be optimized out at compile-time.
detail:: copyImpl ( in_first, in_last, out_first,
typename is_pointer< InputIt> :: type { } ,
typename is_pointer< OutputIt> :: type { } ,
typename is_same< InputElementType, OutputElementType> :: type { } ,
typename is_literal_type< InputElementType> :: type { } ) ;
}
namespace detail {
//The input and output ranges are contiguous, both contain elements of type T and elements are trivially copyable:
template < typename InputIt, typename OutputIt>
OutputIt copyImpl( InputIt in_first, InputIt in_last, OutputIt out_first,
true_type, true_type, true_type, true_type) {
cout << "Chose memset optimized version" << endl;
auto numberOfElements = distance( in_first, in_last) ;
auto numberOfBytes = numberOfElements * sizeof ( * in_first) ;
//We actually need to use memmove because the range requirements differ between
//memcpy and copy. You could further optimize to call memcpy in certain safe cases.
memmove ( out_first, in_first, numberOfBytes) ;
}
//All other cases:
template < typename InputIt, typename OutputIt,
typename InputIsPointerTag, typename OutputIsPointerTag,
typename SameTypesTag, typename TriviallyCopyableTag>
OutputIt copyImpl( InputIt in_first, InputIt in_last, OutputIt out_first,
InputIsPointerTag, OutputIsPointerTag, SameTypesTag, TriviallyCopyableTag) {
cout << "Chose the safe, but general version" << endl;
auto curInItr = in_first;
auto curOutItr = out_first;
while ( curInItr ! = in_last) {
* curOutItr = * curInItr;
++ curInItr;
++ curOutItr;
}
}
} //!detail
} //!mine
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8bGlzdD4KI2luY2x1ZGUgPGNzdHJpbmc+CiNpbmNsdWRlIDxpdGVyYXRvcj4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8YWxnb3JpdGhtPiAvL2ZvciBzdGQ6OmVxdWFsCiNpbmNsdWRlIDxjYXNzZXJ0PgoKdXNpbmcgc3RkOjpjb3V0Owp1c2luZyBzdGQ6OmVuZGw7CnVzaW5nIHN0ZDo6Ym9vbGFscGhhOwp1c2luZyBzdGQ6OnZlY3RvcjsKdXNpbmcgc3RkOjpsaXN0Owp1c2luZyBzdGQ6OmVxdWFsOwp1c2luZyBzdGQ6Om1lbW1vdmU7CnVzaW5nIHN0ZDo6YmVnaW47CnVzaW5nIHN0ZDo6ZW5kOwp1c2luZyBzdGQ6OmRpc3RhbmNlOwp1c2luZyBzdGQ6OmJhY2tfaW5zZXJ0ZXI7CnVzaW5nIHN0ZDo6dHJ1ZV90eXBlOwp1c2luZyBzdGQ6OmlzX3BvaW50ZXI7CnVzaW5nIHN0ZDo6aXNfc2FtZTsKCi8vV291bGQgcHJlZmVyIHN0ZDo6aXNfdHJpdmFsbHlfY29weWFibGUsIGJ1dCBsaWJzdGRjKysgaGFzbid0IGltcGxlbWVudGVkIGl0IHlldC4KdXNpbmcgc3RkOjppc19saXRlcmFsX3R5cGU7CgoKLyoKCiAgVGhpcyBjb2RlIGRlbW9uc3RyYXRlcyB0aGUgdXNlIG9mIHRhZy1kaXNwYXRjaCB0byBpbnRlcm5hbGx5IG9wdGltaXplIHN0ZDo6Y29weQogIGJ5IGNhbGxpbmcgc3RkOjptZW1jcHkgYXMgYW4gaW1wbGVtZW50YXRpb24gZGV0YWlsIHdoZW5ldmVyIGl0IGlzIHNhZmUgdG8gZG8gc28uCgogIFRhZy1kaXNwYXRjaCBpcyBhIHRlY2huaXF1ZSB3aGVyZWJ5IHlvdSB1c2UgdHlwZSB0cmFpdHMgdG8gc2VsZWN0IGEgZnVuY3Rpb24KICBpbXBsZW1lbnRhdGlvbiBhdCBjb21waWxlLXRpbWUgYnkgbGV2ZXJhZ2luZyBvdmVybG9hZGluZy4KCiAgSSBjaG9zZSB0byB1c2UgNCB0eXBlLXRyYWl0cyB0byBtYWtlIHRoZSBkZXRlcm1pbmF0aW9uIG9mIHdoZXRoZXIgb3Igbm90IGl0IGlzCiAgc2FmZS4gWW91IG1heSBiZSBhYmxlIHRvIG9wdGltaXplIGZvciBtb3JlIGNhc2VzIGlmIHlvdSB1c2VkIG1vcmUsIG9yIGEgZGlmZmVyZW50CiAgc2V0IG9mLCB0cmFpdHMuCgogIC1NYXJrCgogKi8KCm5hbWVzcGFjZSBtaW5lIHsgLy9LaWxsIGNvbXBpbGVyIGVycm9yIGJlY2F1c2Ugb2YgbGlic3RkYysrIGJ1ZyAoc29tZWhvdyBzdGQ6OmNvcHkgd2FzIGluIHNjb3BlKQoKLy9EZWNsYXJhdGlvbnM6CnRlbXBsYXRlPHR5cGVuYW1lIElucHV0SXQsIHR5cGVuYW1lIE91dHB1dEl0PgpPdXRwdXRJdCBjb3B5KElucHV0SXQgaW5fZmlyc3QsIElucHV0SXQgaW5fbGFzdCwgT3V0cHV0SXQgb3V0X2ZpcnN0KTsKCm5hbWVzcGFjZSBkZXRhaWwgewoKdGVtcGxhdGU8dHlwZW5hbWUgSW5wdXRJdCwgdHlwZW5hbWUgT3V0cHV0SXQ+Ck91dHB1dEl0IGNvcHlJbXBsKElucHV0SXQgaW5fZmlyc3QsIElucHV0SXQgaW5fbGFzdCwgT3V0cHV0SXQgb3V0X2ZpcnN0LAogICAgICAgICAgICAgICAgICB0cnVlX3R5cGUsIHRydWVfdHlwZSwgdHJ1ZV90eXBlLCB0cnVlX3R5cGUpOwoKdGVtcGxhdGU8dHlwZW5hbWUgSW5wdXRJdCwgdHlwZW5hbWUgT3V0cHV0SXQsCiAgICAgICAgIHR5cGVuYW1lIElucHV0SXNQb2ludGVyVGFnLCB0eXBlbmFtZSBPdXRwdXRJc1BvaW50ZXJUYWcsCiAgICAgICAgIHR5cGVuYW1lIFNhbWVUeXBlc1RhZywgdHlwZW5hbWUgVHJpdmlhbGx5Q29weWFibGVUYWc+Ck91dHB1dEl0IGNvcHlJbXBsKElucHV0SXQgaW5fZmlyc3QsIElucHV0SXQgaW5fbGFzdCwgT3V0cHV0SXQgb3V0X2ZpcnN0LAogICAgICAgICAgICAgICAgICBJbnB1dElzUG9pbnRlclRhZywgT3V0cHV0SXNQb2ludGVyVGFnLCBTYW1lVHlwZXNUYWcsIFRyaXZpYWxseUNvcHlhYmxlVGFnKTsKCn0gLy8hZGV0YWlsCn0gLy8hbWluZQoKCgppbnQgbWFpbigpIHsKICB7CiAgICBpbnQgYVtdID0geyAwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5fTsKICAgIGludCBiWzEwXTsKICAgIG1pbmU6OmNvcHkoYmVnaW4oYSksIGVuZChhKSwgYmVnaW4oYikpOwogICAgYXNzZXJ0KGVxdWFsKGJlZ2luKGEpLCBlbmQoYSksIGJlZ2luKGIpKSk7CiAgfQogIHsKICAgIHZlY3RvcjxpbnQ+IGEgeyAwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5fTsKICAgIHZlY3RvcjxpbnQ+IGI7CiAgICBiLnJlc2l6ZSgxMCk7CiAgICBtaW5lOjpjb3B5KGJlZ2luKGEpLCBlbmQoYSksIGJlZ2luKGIpKTsKICAgIGFzc2VydChlcXVhbChiZWdpbihhKSwgZW5kKGEpLCBiZWdpbihiKSkpOwogIH0KICB7CiAgICBsaXN0PGludD4gYSB7IDAsIDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDl9OwogICAgbGlzdDxpbnQ+IGI7CiAgICBtaW5lOjpjb3B5KGJlZ2luKGEpLCBlbmQoYSksIGJhY2tfaW5zZXJ0ZXIoYikpOwogICAgYXNzZXJ0KGVxdWFsKGJlZ2luKGEpLCBlbmQoYSksIGJlZ2luKGIpKSk7CiAgfQoKICByZXR1cm4gMDsKfQoKCgpuYW1lc3BhY2UgbWluZSB7Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBJbnB1dEl0LCB0eXBlbmFtZSBPdXRwdXRJdD4KT3V0cHV0SXQgY29weShJbnB1dEl0IGluX2ZpcnN0LCBJbnB1dEl0IGluX2xhc3QsIE91dHB1dEl0IG91dF9maXJzdCkgewogIHVzaW5nIElucHV0RWxlbWVudFR5cGUgPSBkZWNsdHlwZSgqaW5fZmlyc3QpOwogIHVzaW5nIE91dHB1dEVsZW1lbnRUeXBlID0gZGVjbHR5cGUoKm91dF9maXJzdCk7CgogIGNvdXQgPDwgYm9vbGFscGhhCiAgICAgICA8PCAiXG5JbnB1dCBpdGVyYXRvciBpcyBwb2ludGVyOlx0IgogICAgICAgPDwgaXNfcG9pbnRlcjxJbnB1dEl0Pjo6dmFsdWUgPDwgJ1xuJwogICAgICAgPDwgIk91dHB1dCBpdGVyYXRvciBpcyBwb2ludGVyOlx0IgogICAgICAgPDwgaXNfcG9pbnRlcjxPdXRwdXRJdD46OnZhbHVlIDw8ICdcbicKICAgICAgIDw8ICJJbnB1dCBhbmQgb3V0cHV0IGl0ZXJhdG9ycyBkZXJlZiB0byB0aGUgc2FtZSB0eXBlOlx0IgogICAgICAgPDwgaXNfc2FtZTxJbnB1dEVsZW1lbnRUeXBlLCBPdXRwdXRFbGVtZW50VHlwZT46OnZhbHVlIDw8ICdcbicKICAgICAgIDw8ICJFbGVtZW50IGlzIHRyaXZpYWxseSBjb3B5YWJsZTpcdCIKICAgICAgIDw8IGlzX2xpdGVyYWxfdHlwZTxJbnB1dEVsZW1lbnRUeXBlPjo6dmFsdWUgPDwgJ1xuJyA8PCBlbmRsOwoKICAvL1VzZSB0YWctZGlzcGF0Y2ggdGVjaG5pcXVlIHRvIHNlbGVjdCB0aGUgcmlnaHQgaW1wbGVtZW50YXRpb24gZnVuY3Rpb24uCiAgLy9UaGUgb2JqZWN0cyB3ZSBjcmVhdGUgZm9yIHRhZyBkaXNwYXRjaCB3aWxsIGJlIG9wdGltaXplZCBvdXQgYXQgY29tcGlsZS10aW1lLgogIGRldGFpbDo6Y29weUltcGwoaW5fZmlyc3QsIGluX2xhc3QsIG91dF9maXJzdCwKICAgICAgICAgICAgICAgICAgIHR5cGVuYW1lIGlzX3BvaW50ZXI8SW5wdXRJdD46OnR5cGV7fSwKICAgICAgICAgICAgICAgICAgIHR5cGVuYW1lIGlzX3BvaW50ZXI8T3V0cHV0SXQ+Ojp0eXBle30sCiAgICAgICAgICAgICAgICAgICB0eXBlbmFtZSBpc19zYW1lPElucHV0RWxlbWVudFR5cGUsIE91dHB1dEVsZW1lbnRUeXBlPjo6dHlwZXt9LAogICAgICAgICAgICAgICAgICAgdHlwZW5hbWUgaXNfbGl0ZXJhbF90eXBlPElucHV0RWxlbWVudFR5cGU+Ojp0eXBle30pOwp9CgoKCm5hbWVzcGFjZSBkZXRhaWwgewoKLy9UaGUgaW5wdXQgYW5kIG91dHB1dCByYW5nZXMgYXJlIGNvbnRpZ3VvdXMsIGJvdGggY29udGFpbiBlbGVtZW50cyBvZiB0eXBlIFQgYW5kIGVsZW1lbnRzIGFyZSB0cml2aWFsbHkgY29weWFibGU6CnRlbXBsYXRlPHR5cGVuYW1lIElucHV0SXQsIHR5cGVuYW1lIE91dHB1dEl0PgpPdXRwdXRJdCBjb3B5SW1wbChJbnB1dEl0IGluX2ZpcnN0LCBJbnB1dEl0IGluX2xhc3QsIE91dHB1dEl0IG91dF9maXJzdCwKICAgICAgICAgICAgICB0cnVlX3R5cGUsIHRydWVfdHlwZSwgdHJ1ZV90eXBlLCB0cnVlX3R5cGUpIHsKCiAgY291dCA8PCAiQ2hvc2UgbWVtc2V0IG9wdGltaXplZCB2ZXJzaW9uIiA8PCBlbmRsOwoKICBhdXRvIG51bWJlck9mRWxlbWVudHMgPSBkaXN0YW5jZShpbl9maXJzdCwgaW5fbGFzdCk7CiAgYXV0byBudW1iZXJPZkJ5dGVzID0gbnVtYmVyT2ZFbGVtZW50cyAqIHNpemVvZigqaW5fZmlyc3QpOwogIC8vV2UgYWN0dWFsbHkgbmVlZCB0byB1c2UgbWVtbW92ZSBiZWNhdXNlIHRoZSByYW5nZSByZXF1aXJlbWVudHMgZGlmZmVyIGJldHdlZW4KICAvL21lbWNweSBhbmQgY29weS4gWW91IGNvdWxkIGZ1cnRoZXIgb3B0aW1pemUgdG8gY2FsbCBtZW1jcHkgaW4gY2VydGFpbiBzYWZlIGNhc2VzLgogIG1lbW1vdmUob3V0X2ZpcnN0LCBpbl9maXJzdCwgbnVtYmVyT2ZCeXRlcyk7Cn0KCi8vQWxsIG90aGVyIGNhc2VzOgp0ZW1wbGF0ZTx0eXBlbmFtZSBJbnB1dEl0LCB0eXBlbmFtZSBPdXRwdXRJdCwKICAgICAgICAgdHlwZW5hbWUgSW5wdXRJc1BvaW50ZXJUYWcsIHR5cGVuYW1lIE91dHB1dElzUG9pbnRlclRhZywKICAgICAgICAgdHlwZW5hbWUgU2FtZVR5cGVzVGFnLCB0eXBlbmFtZSBUcml2aWFsbHlDb3B5YWJsZVRhZz4KT3V0cHV0SXQgY29weUltcGwoSW5wdXRJdCBpbl9maXJzdCwgSW5wdXRJdCBpbl9sYXN0LCBPdXRwdXRJdCBvdXRfZmlyc3QsCiAgICAgICAgICAgICAgSW5wdXRJc1BvaW50ZXJUYWcsIE91dHB1dElzUG9pbnRlclRhZywgU2FtZVR5cGVzVGFnLCBUcml2aWFsbHlDb3B5YWJsZVRhZykgewoKICBjb3V0IDw8ICJDaG9zZSB0aGUgc2FmZSwgYnV0IGdlbmVyYWwgdmVyc2lvbiIgPDwgZW5kbDsKCiAgYXV0byBjdXJJbkl0ciA9IGluX2ZpcnN0OwogIGF1dG8gY3VyT3V0SXRyID0gb3V0X2ZpcnN0OwogIHdoaWxlKGN1ckluSXRyICE9IGluX2xhc3QpIHsKICAgICpjdXJPdXRJdHIgPSAqY3VySW5JdHI7CiAgICArK2N1ckluSXRyOwogICAgKytjdXJPdXRJdHI7CiAgfQp9Cgp9IC8vIWRldGFpbAp9IC8vIW1pbmUK