2010-10-04 4 views
1

Я попытался написать короткую функцию, чтобы инвертировать std::map<K, V> (я знаю об boost.bimap, это для самообразования), и, к моему удивлению, я нашел, что код, который GCC 4.4 принял с помощью -pedantic -ansi settings, был отклонен как const-неправильный SunCC (5.8, с 2005).могут ли функторы, вызываемые из алгоритмов, действующих на карте, принимать пару <K, V> вместо value_type?

С value_type является std::pair<const K, V>, SunCC настаивал на том, что я Уст-квалифицировать мой K тип в аргументы функции, которые передаются transform() и for_each(), и в типе возвращаемого значения должны быть переданы std::inserter, насколько я может сказать, это может быть правильно? Какой компилятор соответствует стандартам?

#include <iostream> 
#include <iterator> 
#include <map> 
#include <string> 
#include <algorithm> 
template<typename K, typename V> 
std::pair<V, K> flip_pair(const std::pair<K, V>& p) // GCC/MSVC 
//std::pair<const V, K> flip_pair(const std::pair<const K, V>& p) // SunCC 
{ 
    return std::make_pair(p.second, p.first); // GCC/MSVC 
//  return std::pair<const V, K>(p.second, p.first); // SunCC 
} 
template<typename K, typename V> 
std::multimap<V, K> invert_map(const std::map<K, V>& in) 
{ 
    std::multimap<V, K> out; 
    transform(in.begin(), in.end(), std::inserter(out, out.begin()), 
       flip_pair<K, V>); 
    return out; 
} 
void print_pair(const std::pair<int, std::string>& p) // GCC/MSVC 
//void print_pair(const std::pair<const int, std::string>& p) // SunCC 
{ 
     std::cout << p.first << '\t' << p.second << '\n'; 
} 
int main() 
{ 
    std::map<std::string, int> map; 
    map["foo"] = 1; map["bar"] = 2; map["baz"] = 3; 
    std::multimap<int, std::string> revmap = invert_map(map); 
    for_each(revmap.begin(), revmap.end(), print_pair); 
} 
+0

Поддерживает ли эта версия шаблона члена поддержки компилятора Sun? Если это не так, это может объяснить отсутствие конструкторов безсловного преобразования 'template template std :: pair :: pair (const std :: pair &);'. – aschepler

+0

@aschepler: Этот конструктор #defined с _RWSTD_NO_MEMBER_TEMPLATES в моей системе, оказывается. Но одна и та же программа компилируется с '-library = stlport4', которая выбирает другой набор включений. В конце концов, сам компилятор не виноват. – Cubbi

ответ

3

Visual C++ и g ++ верны; этот код (с flip_pair<K, V>() с const std::pair<K, V>&) в порядке.

Внутри transform, flip_pair<K, V> вызывается. Поскольку объект, передаваемый этой функции, является pair<const K, V>, создается временный объект типа pair<K, V> (pair имеет конвертирующий конструктор, который позволяет конвертировать один тип пары в другой, если типы и .second являются конвертируемыми).

Это временное сообщение передано flip_pair<K, V>(), воспользовавшись тем, что ссылка const может быть привязана к временному.

+0

Не создает временную 'пару ' отбрасывать определители const? Не было бы более уместным просто квалифицировать тип как 'pair ' в этих функциях? – JoshD

+0

@JoshD, компилятор не отбрасывал квалификаторы в типе. И типы в flip_pair будут: flip_pair :: value_type :: first_type, std :: map :: value_type :: second_type>, который будет расширяться до: flip_pair : : key_type, std :: map :: mapped_type>. Другими словами, K является const K в создании flip_pair в invert_map, поэтому дополнительный определитель констант не нужен. – MSN

+0

Простой, как всегда! Забыл об этом конструкторе, смущенный ошибками «неправильного типа при создании». – Cubbi