У меня есть следующий код для проверки одной концепции из более крупной программы, и я пытаюсь скомпилировать с GCC 4.1.1 на Linux. Я не могу использовать более новую версию компилятора из-за ограничений корпоративной среды, поэтому мне нужно сделать так, чтобы он компилировался и работал с текущей доступной версией компилятора.
// test.cpp - my tr1::unordered_map usage example
#include <iostream>
#include <tr1/unordered_map>
namespace YY {
class X { public: X(int z_val = 0); private: int z; };
inline X::X(int z_val) : z(z_val) {}
enum XTE { Xt1, Xt2, Xt3 };
}
namespace std { namespace tr1 {
#define _my_tr1_hashtable_define_trivial_hash(T) \
template<> \
struct hash<T> \
: public std::unary_function<T, std::size_t> \
{ \
std::size_t \
operator()(T val) const \
{ return static_cast<std::size_t>(val); } \
}
_my_tr1_hashtable_define_trivial_hash(YY::XTE);
#undef _my_tr1_hashtable_define_trivial_hash
}}namespace YY {
typedef std::tr1::unordered_map<long long, X*> TXM;
typedef std::tr1::unordered_map<XTE, TXM> TTXM;
}
int main()
{
YY::TTXM m;
std::cout << m.size();
return 0;
}
Затем я пытаюсь скомпилировать этот код, gcc выдает мне следующую ошибку:
$ g ++ -c test.cpp /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/tr1/hashtable: в экземпляре Б─≤Internal :: hash_code_base, Internal :: extract1st>, std :: equal_to, std :: tr1 :: hash, Internal :: mod_range_hashing, Internal :: default_ranged_hash, false> Б─≥: /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/tr1/hashtable:1014: создается из Б─≤std: : tr1 :: hashtable, std :: allocator>, Internal :: extract1st>, std :: equal_to, std :: tr1 :: hash, Internal :: mod_range_hashing, Internal :: default_ranged_hash, Internal :: prime_rehash_policy, false, false, правда> Б─≥ /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/tr1/unordered_map:63: создается из Б─≤std: : tr1 :: unordered_map, std :: equal_to, std :: allocator>, false> Б─≥ /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/bits/stl_pair.h:74: создан из Б─≤ std :: pair, std :: equal_to, std :: allocator>, false>> Б─≥ /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/tr1/hashtable:413: создается из Б─≤Internal: : extract1st, std :: equal_to, std :: allocator>, false>>> Б─≥ /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/tr1/hashtable:861: создается из Б─≤Internal: : hash_code_base, std :: equal_to, std :: allocator>, false>>, Internal :: extract1st, std :: equal_to, std :: allocator>, false>>>, std :: equal_to, std :: tr1 :: hash, Internal :: mod_range_hashing, Internal :: default_ranged_hash, false> Б─≥ /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/tr1/hashtable:1014: создается из Б─≤std: : tr1 :: hashtable, std :: equal_to, std :: allocator>, false>>, std :: allocator, std :: equal_to, std :: allocator>, false>>>, Internal :: extract1st, std :: equal_to, std :: allocator>, false>>>, std :: equal_to, std :: tr1 :: hash, Internal :: mod_range_hashing, Internal :: default_ranged_hash, Internal :: prime_rehash_policy, false, false, true> Б─≥ /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/tr1/unordered_map:63: создается из Б─≤std: : tr1 :: unordered_map, std :: equal_to, std :: allocator>, false>, std :: tr1 :: hash, std :: equal_to, std :: allocator, std :: equal_to, std :: allocator>, false >>>, false> Б─≥ test.cpp: 42: создается здесь /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/tr1/hashtable:863: ошибка: Б─≤Internal: : hash_code_base :: m_h1Б─≥ имеет неполный тип /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/tr1/functional:1101: ошибка: объявление Б─≤ struct std :: tr1 :: hashБ─≥
test.cpp: 42: создается здесь
является
YY::TTXM m;
Если я изменю
typedef std::tr1::unordered_map<XTE, TXM> TTXM;
в
typedef std::tr1::unordered_map<XTE, TXM*> TTXM;
он успешно компилируется, но я не хочу этого делать.
Есть идеи, предложения, как заставить это работать?
Он жалуется, что не имеет хэш-функции для long long
так что просто добавь
_my_tr1_hashtable_define_trivial_hash(long long);
и тебе должно быть хорошо идти.
Постскриптум Я думаю, что причина использования TXM * вместо TXM работает потому, что компилятору не нужно разрешать тип TXM, если он является указателем, поэтому он не идет по пути выяснения, что у него нет всего должен создать этот тип .. а именно длинную длинную хеш-функцию. Если бы вы позже попытались создать экземпляр объекта TXM, он бы потом пожаловался вам на ошибку, аналогичную той, что вы видите сейчас.
Других решений пока нет …