Russian Qt Forum
Апрель 19, 2024, 03:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема с qHash [решено]  (Прочитано 5021 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Май 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 &). Конечно если поместить инклуд после этой ф-ции - все норм, но елы-палы..

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

Гребаная темплейтщина  Плачущий
« Последнее редактирование: Май 04, 2019, 11:22 от Igors » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #1 : Май 03, 2019, 15:16 »

Я на это тоже натыкался, как раз проблема, имхо, в том, что qHash НЕ темплейтная. То есть у вас все оверлоады должны быть включены ДО класса QHash
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #2 : Май 03, 2019, 16:19 »

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

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Май 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 нету

Спасибо
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Май 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;
}
 
« Последнее редактирование: Май 04, 2019, 11:22 от Igors » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #5 : Май 04, 2019, 11:45 »

Неплохо кстати!
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.136 секунд. Запросов: 22.