Специализированный шаблон hashmap - PullRequest
3 голосов
/ 11 февраля 2011

Я использую hash_map в C ++ и хочу предоставить для него упрощенное имя типа:

Тип ключа и хэш-функция всегда одинаковы.

stdext::hash_map<std::string, [MAPPED TYPE], CStringHasher>

Однако я не хочу писать все это каждый раз, когда объявляю хэш-карту, которая отображает строки в тип X.

  • Могу ли я написать шаблон или макрос, который упрощает это?

Таким образом, вышеприведенное объявление будет выглядеть так:

template<typename T> StringHashmap = stdext::hash_map<std::string, T, CStringHasher>

StringHashmap<int> mapA; //Maps std::string to int
StringHashamp<bool> mapB; //Maps std::string to bool

Ответы [ 3 ]

5 голосов
/ 11 февраля 2011

Как уже говорили другие, шаблонные псевдонимы - путь, если вы можете использовать C ++ 0x:

template < typename MappedType >
using StringHashMap = stdext::hash_map< std::string, MappedType, CStringHasher >;

StringHashMap< int > mapA;
StringHashMap< bool > mapB;

(Как заметил @MSalters, если у вас есть доступный C ++ 0x, вам, вероятно, следуетиспользуйте std::unordered_map.)

В противном случае вы все равно можете использовать обычный обходной путь, который заключается в определении шаблона класса, содержащего typedef:

template < typename MappedType >
struct StringHashMap
{
    typedef stdext::hash_map< std::string, MappedType, CStringHasher > type;
};

StringHashMap< int >::type mapA;
StringHashMap< bool >::type mapB;

Недостаток этого решения (который имеет многие вопросы здесь о SO) заключаются в том, что вам иногда нужно префикс StringHashMap< T >::type ключевым словом typename, чтобы утверждать компилятору, что это имя фактически обозначает тип.Я не буду останавливаться на этом вопросе в этом ответе, вы можете проверить этот FAQ , и особенно принятый ответ, для получения дополнительной информации.(Спасибо @sbi за то, что вызвали этот вопрос.)

2 голосов
/ 11 февраля 2011

С текущей версией C ++ (C ++ 03) действительно нет хорошего способа сделать это.Вы можете попробовать что-то вроде

#define StringHashMap(type) stdext::hash_map<std::string, type, CStringHasher>

Но тогда у вас возникнут проблемы, если вы попытаетесь указать тип шаблона с запятой в нем, например:

StringHashMap(pair<int, string>) myMap; // Error!

Это не удается, потому чтопрепроцессор маркирует это как

StringHashMap((pair<int), (string>)) myMap; // Error!

, что не то, что вы хотите.Если вы не собираетесь делать что-то подобное, все будет в порядке.В качестве альтернативы вы можете использовать typedef s, чтобы обойти это:

typedef pair<int, int> IntPair;
StringHashMap(IntPair) myMap; // Okay

Если вы разрешаете использовать функции C ++ 0x, вы можете использовать шаблон, используя объявление, как здесь:

template <typename T>
    using StringHashMap = stdext::hash_map<std::string, T, CStringHasher>;

К сожалению, в C ++ 03 нет функции «template typedef», подобной этой, поэтому вам придется использовать более новый компилятор и не будет столь же хорошей гарантии переносимости.

Эй, подожди минутку!Меня зовут templatetypedef, и я впервые в «Переполнении стека» написал эту фразу в ответе!Ты только что сделал мою ночь.: -)

1 голос
/ 11 февраля 2011

Если вы используете C ++ 0x, шаблон typedefs был разработан, чтобы делать именно такие вещи:

http://en.wikipedia.org/wiki/C%2B%2B0x#Template_aliases

...