
#include <type_traits>
#include <cstring>

#include <string>
#include <array>

#include <iostream>

using namespace std;

template<typename T> void fast_copy_impl(const T* first, const T* last, T* result, std::true_type) {
    cout << "memcpy" << endl;
    memcpy(result, first, (last - first)*sizeof(T) );
}

template<typename T> void fast_copy_impl(const T* first, const T* last, T* result, std::false_type) {
    cout << "copy" << endl;
    copy( first, last, result );
}

template<class T> void fast_copy(const T* first, const T* last, T* result) {
    fast_copy_impl(first, last, result, is_trivially_copyable<T>( ));
}

class Foo {
public:
    Foo() : value_(0) {}
private:
    int value_;
};
class Goo {
public:
    Goo() : value_(0) {}
	Goo(const Goo& goo) : value_(goo.value_)  {}
private:
    int value_;
};

int main() {
    static const int SIZE = 10;
    array<Foo, SIZE> src1, dest1;
    array<Goo, SIZE> src2, dest2;

	array<int, SIZE> src3, dest3;
	array<string, SIZE> src4, dest4;

    fast_copy(src1.data(), src1.data() + src1.size(), dest1.data() );
    fast_copy(src2.data(), src2.data() + src2.size(), dest2.data() );
	fast_copy(src3.data(), src3.data() + src3.size(), dest3.data() );
	fast_copy(src4.data(), src4.data() + src4.size(), dest4.data() );
	return 0;
}
