Что мне действительно нужно, так это переносимое сравнение и печать идентификаторов * nix pthread (pthread_t).Функция pthread_equal существует для сравнения двух идентификаторов потоков на равенство, однако невозможно сравнить их с операторами <<=> => (я имею в виду, конечно, переносимые), потому что в некоторых реализациях pthread_t является указателем на структуру.Поэтому я нашел решение, которым хотел бы поделиться и обсудить его переносимость.
Предположим, у нас есть оболочка класса thred_id, которая должна быть менее сопоставимой, сопоставимой по равенству и, конечно же, пригодной для печати.Я делаю шаблонный класс с двумя частичными специализациями - один для указателей и один для арифметических типов
template <typename T, bool A = is_arithmetic<T>::value>
struct hash
{
static unsigned long calculate(T thread_id)
{
return hash<T*, A>::calculate(&thread_id);
}
};
template <typename T>
struct hash<T*, false>
{
static unsigned long calculate(T* thread_id)
{
std::size_t hash = 0;
if (char* data = reinterpret_cast<char*>(thread_id))
{
for (int i = 0; i < sizeof(T); ++i)
{
hash = (hash << 6) ^ (hash >> 26) ^ data[i];
}
}
return hash;
}
};
template <typename T>
struct hash<T, true>
{
static unsigned long calculate(T thread_id)
{
return static_cast<unsigned long>(thread_id);
}
};
Так как это работает.Если нам нужно сравнить два идентификатора потока, мы просто вызываем
pthread_equal(tid1, tid2);
, но для оператора <мы используем хеш для сравнения </p>
hash<pthread_t>::calculate(tid1) < hash<pthread_t>::calculate(tid2)
Так что здесь
, если pthread_t
реализован как указатель, тогда мы вычислим хеш для указанного объекта.
Если это арифметический тип, то мы просто попытаемся привести его к типу без знака.
Если он реализован какструктура - мы рассчитаем хеш для самого объекта структуры.
Значение хеша будет использоваться только для оператора без вывода и вывода идентификатора потока.
Что вы думаете об этом?Насколько портативно это решение и есть ли что-нибудь лучше этого?
Спасибо всем заранее.