MrCoder said:
Thanks for the answers guys!
Im going to try it using memcmp shortly and see what sort of speed
increase I get.
When you know the size, you can also unroll (or partially unroll) the loop.
This is a semi-generalized implementation:
#include <functional>
#include <iterator>
// identity
template<class T> struct identity {
typedef T type;
};
// map_integral
template<class T, T V> struct map_integral {
static const T value = V;
};
template<class T, T V> const T map_integral<T, V>::value;
// enable_if
template<bool, class R> struct enable_if { };
template<class R> struct enable_if<true, R> : identity<R> { };
// is_class
template<class T> class is_class {
private:
template<class U> static char check(int U::*);
template<class U> static char (& check(...))[2];
public:
static const bool value = sizeof(check<T>(0)) == 1;
};
template<class T> const bool is_class<T>::value;
// is_same
template<class T, class U> struct is_same : map_integral<bool, false> { };
template<class T> struct is_same<T, T> : map_integral<bool, true> { };
// is_pointer_to_function
template<class> struct is_pointer_to_function
: map_integral<bool, false> { };
template<> struct is_pointer_to_function<void*>
: map_integral<bool, false> { };
template<class T> struct is_pointer_to_function<T*>
: is_same<void (T), void (T*)> { };
// is_reference_to_function
template<class> struct is_reference_to_function
: map_integral<bool, false> { };
template<class T> struct is_reference_to_function<T&>
: is_same<void (T), void (T*)> { };
// compare
namespace detail {
template<class iterator, class predicate>
bool compare(
iterator a1, iterator a2,
iterator b1, iterator b2,
predicate pred, std::input_iterator_tag
) {
while (a1 != a2) {
if (b1 == b2 || !pred(*a1++, *b1++)) {
return false;
}
}
return b1 == b2;
}
template<class iterator, class predicate>
bool compare(
iterator a1, iterator a2,
iterator b1, iterator b2,
predicate pred, std::random_access_iterator_tag
) {
typedef typename std::iterator_traits<iterator>::difference_type
difference_type;
difference_type size(a2 - a1);
if (size != b2 - b1) {
return false;
}
// unrolling factor == 4
register difference_type n((size + 3) / 4);
#define body() \
if (!pred(*a1++, *b1++)) { \
return false; \
} \
/**/
switch (size % 4 - !size) {
case 0:
do {
body()
case 3: body()
case 2: body()
case 1: body()
} while (--n);
}
#undef body
return true;
}
} // detail
template<class iterator, class predicate>
inline bool compare(
iterator a1, iterator a2,
iterator b1, iterator b2,
predicate pred
) {
return detail::compare(
a1, a2, b1, b2,
pred, typename std::iterator_traits<iterator>::iterator_category()
);
}
template<class iterator>
inline bool compare(iterator a1, iterator a2, iterator b1, iterator b2) {
return compare(
a1, a2, b1, b2,
std::equal_to<typename std::iterator_traits<iterator>::value_type>()
);
}
template<class T, class predicate>
inline bool compare(const T* a, const T* b, unsigned size, predicate pred) {
return compare(a, a + size, b, b + size, pred);
}
template<class T, unsigned long s1, unsigned long s2, class predicate>
inline typename enable_if<
is_class<predicate>::value
|| is_pointer_to_function<predicate>::value
|| is_reference_to_function said:
::type compare(T (& a)[s1], T (& b)[s2], predicate pred) {
return compare(a, a + s1, b, b + s2, pred);
}
template<class T> inline bool compare(const T* a, const T* b, unsigned size) {
return compare(a, b, size, std::equal_to<const T>());
}
template<class T, unsigned long s1, unsigned long s2>
inline bool compare(T (& a)[s1], T (& b)[s2]) {
return compare(a, b, std::equal_to<T>());
}
Regards,
Paul Mensonides