Уменьшение сложности шаблона в C ++ - PullRequest
8 голосов
/ 04 декабря 2010

Недавно я использовал одну из редко используемых функций STL - пользовательские распределители, и мне нужна серьезная помощь в сокращении моих семантических накладных расходов. Возьмем, например, определение неупорядоченной карты, которая отображает имена файлов в неупорядоченную карту пары целых и shared_ptr в токен, но с использованием специального распределителя.

typedef std::pair<int, int> token_key_type;
typedef std::unordered_map<
    token_key_type, 
    std::shared_ptr<Token>,
    std::hash<token_key_type>,
    std::equal_to<token_key_type>,
    Allocator<
        std::pair<
            const token_key_type, 
            std::shared_ptr<
                Token
            >
        >
    >
> filename_map_value_type;
std::unordered_map<
    string, 
    filename_map_value_type,
    std::hash<string>,
    std::equal_to<string>,
    Allocator<
        std::pair<
            const string, 
            filename_map_value_type
        >
    >
> tokens;

Это 404 символа определений. И затем, чтобы построить его, я должен передать значение по умолчанию для каждого аргумента шаблона, кроме Allocator, который не может быть создан по умолчанию, И счетчик сегментов, для которого не существует определения, в результате чего еще 168 символов просто для построения черт побери. Плюс, конечно же, снова и снова каждый раз, когда я хочу вставить, потому что тип значения первой карты тоже должен быть построен таким же образом.

Есть ли способ избежать всего этого без написания моей собственной unordered_map? Это серьезно начинает замедлять мою производительность.

Редактировать: Извините! Я имел в виду, в общем, для контейнеров STL, а не просто unordered_map, это просто худший случай. У меня также есть эта проблема с регулярным отображением, unordered_set и т. Д., И я не могу написать функцию, которая сделает все это для всех возможных контейнеров STL, которые могут понадобиться мне по отдельности.

Ответы [ 2 ]

6 голосов
/ 04 декабря 2010
Решение

icecrime также может быть сделано с чуть более уродливым старым компилятором с помощью кода ниже. Вы также можете добавить фабричные функции, чтобы упростить конструкцию.

template<typename K, typename V> struct unordered_map_type
{
    typedef std::unordered_map<
        K, 
        V,
        std::hash<K>,
        std::equal_to<K>,
        Allocator<
            std::pair<const K, V>
        >
    > type;
};

typedef std::pair<int, int> token_key_type;
typedef unordered_map_type<token_key_type, std::shared_ptr<Token> >::type filename_map_value_type;
6 голосов
/ 04 декабря 2010

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

template<class Key, class Value>
using custom_unordered_map = std::unordered_map
    <
        Key,
        Value,
        std::hash<Key>,
        std::equal_to<Value>,
        Allocator<std::pair<const Key, Value>>
    >;

typedef custom_unordered_map<token_key_type, std::shared_ptr<Token>> filename_map_value_type;
typedef custom_unordered_map<std::string, filename_map_value_type> your_typedef_name;

Еще раз, извините, если это не скомпилируется.

Также обратите внимание, что это уже было возможно в C ++ 03 с использованием дополнительного типа «косвенность»:

template<class Key, class Value>
struct custom_unordered_map
{
    typedef std::unordered_map
    <
        Key,
        Value,
        std::hash<Key>,
        std::equal_to<Value>,
        Allocator<std::pair<const Key, Value> >
    > type;
};

typedef custom_unordered_map<token_key_type, std::shared_ptr<Token> >::type filename_map_value_type;
typedef custom_unordered_map<std::string, filename_map_value_type>::type your_typedef_name;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...