Russian Qt Forum

Программирование => С/C++ => Тема начата: Igors от Май 03, 2019, 15:05



Название: Проблема с qHash [решено]
Отправлено: Igors от Май 03, 2019, 15:05
Добрый  день

"Элементарный" пример
Код
C++ (Qt)
#include <QSet>
#include <QString>
// #include "QHashProb.h"
 
uint qHash( const std::string & str )
{
return qHash(QString::fromStdString(str));
}
 
#ifndef QHASHPROB_H
template <class T>
struct CTest {
CTest( const T & a ) : m_a(a) {}
bool operator == ( const CTest & other ) const { return m_a == other.m_a; }
 
T m_a;
};
 
template<class T>
uint qHash( const CTest<T> & test )
{
return qHash(test.m_a);
}
#endif
 
 
int main( void )
{
QSet<CTest<std::string>> set1;
set1.insert(std::string("abc"));
 
return 0;
}
 
Все работает, нема квешнзов. Теперь раскомментируем третью строку - текст из #ifndef теперь в хедере (zip приаттачен). Хирак - шланг теперь не находит qHash(const std::string &). Конечно если поместить инклуд после этой ф-ции - все норм, но елы-палы..

Какого <> он щемится до "инстанциации"? Почему считает что в хедере все должно быть известно? Ну объявлена нужная ф-ция позже, но ведь до инстанциации и в той же единице трансляции. Или как?

Гребаная темплейтщина  :'(


Название: Re: Проблема с qHash
Отправлено: Авварон от Май 03, 2019, 15:16
Я на это тоже натыкался, как раз проблема, имхо, в том, что qHash НЕ темплейтная. То есть у вас все оверлоады должны быть включены ДО класса QHash


Название: Re: Проблема с qHash
Отправлено: ssoft от Май 03, 2019, 16:19
Это известный существенный косяк в архитектуре QHash. Хеш функция объявлена, как функция, а не как специализация класса hash (https://ru.cppreference.com/w/cpp/utility/hash).
Поэтому функция qHash должна быть объявлена ДО включения заголовка QHash.


Название: Re: Проблема с qHash
Отправлено: Igors от Май 04, 2019, 11:02
Да, вот еще более простой (или вызывающий) пример
Код
C++ (Qt)
#include <QSet>
#include <QString>
 
uint qHash( const std::string & str )
{
return qHash(QString::fromStdString(str));
}
 
int main( void )
{
QSet<std::string> set;
set.insert(std::string("abc"));
 
return 0;
}
 
Не компилится. Придется выносить qHash в хедер и включать "до того". Оказывается надо было делать спецификацией
Код
C++ (Qt)
template<>
uint qHash<std::string>( const std::string & str )
{
return qHash(QString::fromStdString(str));
}
 
Но что тогда писать до спецификации
Код:
template<class T>
uint qHash( const T & t )
{
   ???
}
Чтобы компилятор вякал если нужного qHash нету

Спасибо


Название: Re: Проблема с qHash
Отправлено: Igors от Май 04, 2019, 11:20
Ага, понял - ничего, достаточно описания. Вот полный текст
хедер
Код
C++ (Qt)
// qHashProb.h
 
#ifndef QHASHPROB_H
#define QHASHPROB_H
 
template <class T>
struct CTest {
CTest( const T & a ) : m_a(a) {}
bool operator == ( const CTest & other ) const { return m_a == other.m_a; }
 
T m_a;
};
 
template<class T>
uint qHash( const T & );
 
template<class T>
uint qHash( const CTest<T> & test )
{
return qHash(test.m_a);
}
 
#endif // QHASHPROB_H
 
cpp файл
Код
C++ (Qt)
// qHashProb.cpp
 
#include <QSet>
#include <QString>
#include "qHashProb.h"
 
template<>
uint qHash<std::string>( const std::string & str )
{
return qHash(QString::fromStdString(str));
}
 
int main( void )
{
// кастомный qHash
QSet<CTest<std::string>> set1;
set1.insert(std::string("abc"));
 
// стандартный qHash
QSet<CTest<QString>> set2;
set2.insert(QString("abc"));
 
return 0;
}
 


Название: Re: Проблема с qHash [решено]
Отправлено: Авварон от Май 04, 2019, 11:45
Неплохо кстати!