When two values are equal, when one comes before the other, and when their bits agree.
More...
template<typename L, typename R = L>
struct tts::comparison< L, R >
When two values are equal, when one comes before the other, and when their bits agree.
Specialize this for your own types rather than overloading the free functions: a specialization that does not match is a compilation error, where a misnamed overload used to be ignored in silence.
The three members are equal, less and bit_equal. Write the ones the type needs and leave the rest out: their defaults are operator==, operator< and a memcmp over the whole object. That last one reads padding, so a type whose storage is wider than the value it carries, such as a SIMD register wider than the lanes it holds, has to write bit_equal.
Both operand types are parameters, in the order they are written, so a comparison between two different types is specialized on the pair rather than on either side of it.
The compare_equal and compare_less free functions this replaces are gone. An overload left behind is reported where it would have been used, rather than ignored in silence.
- Template Parameters
-
| L | Type of the left-hand operand |
| R | Type of the right-hand operand, the same as L unless stated otherwise |
#define TTS_MAIN
#include <tts/tts.hpp>
namespace sample
{
template<typename T> struct box
{
T value;
};
}
namespace tts
{
template<
typename T>
struct comparison<sample::box<T>, sample::box<T>>
{
static bool equal(sample::box<T> const& l, sample::box<T> const& r)
{
return l.value == r.value;
}
};
}
TTS_CASE(
"Compare values with custom equality")
{
sample::box<int> a {42};
sample::box<int> b {13};
};
A specialization that answers for less as well covers the ordering macros.
#define TTS_MAIN
#include <tts/tts.hpp>
#include <cmath>
namespace sample
{
template<typename T> struct absolute
{
T value;
};
}
namespace tts
{
template<
typename T>
struct comparison<sample::absolute<T>, sample::absolute<T>>
{
static bool equal(sample::absolute<T> const& l, sample::absolute<T> const& r)
{
return std::abs(l.value) == std::abs(r.value);
}
static bool less(sample::absolute<T> const& l, sample::absolute<T> const& r)
{
return std::abs(l.value) < std::abs(r.value);
}
};
}
TTS_CASE(
"Compare values with custom comparisons")
{
sample::absolute<int> a {42};
sample::absolute<int> b {-42};
sample::absolute<int> c {-13};
};
A type whose storage is wider than the value it carries answers for bit_equal.
#define TTS_MAIN
#include <tts/tts.hpp>
namespace sample
{
struct tagged_word
{
std::uint8_t tag;
std::uint64_t storage;
};
}
namespace tts
{
template<>
struct comparison<sample::tagged_word, sample::tagged_word>
{
static bool bit_equal(sample::tagged_word const& l, sample::tagged_word const& r)
{
return l.tag == r.tag;
}
};
}
TTS_CASE(
"Compare values by the bits that carry them")
{
sample::tagged_word const a {7, 0};
sample::tagged_word const b {7, 0xDEADBEEF};
sample::tagged_word const c {9, 0};
};