2016-12-28 10 views
2
#include <map> 
#include <string> 
#include <string_view> 

using namespace std; 

int main() 
{ 
    string_view key = "hello";  
    map<string, int, less<>> coll; 
    coll.find(key); // ok 
    coll[key] = 0; // !!! error ??? 
} 

Ключ типа std::string, совместимый тип std::string_view. Поскольку C++ 14, std::map::find позволяет использовать совместимый ключ; так что coll.find(key); в порядке.Почему std :: map не всегда допускает совместимый тип в качестве ключа?

Однако Почему нетcoll[key] = 0;ОК тоже?

+1

Поскольку [] не получило более перегрузки в 14, в отличие от find ...? – deviantfan

+1

'operator []' также вставляет, если не найден – Danh

+1

@deviantfan, Почему бы не перегрузить []? – xmllmx

ответ

3

Обоснование было описано в N3465.

Концептуально расширение состоит в замене оригинальной формулировки на основе строгих слабых порядков, основанной на понятии разбиения последовательностей, как это было впервые предложено Дэвидом Абрахамом. К сожалению, этот процесс расширения не был выполнен для операций поиска ассоциативных контейнеров, которые все еще сформулированы в терминах строгих слабых порядков и, таким образом, не допускают гетерогенных сопоставлений .

Возьмем такого примера из N3465, и изменить его немного:

struct name_entry 
{ 
    std::string family_name; 
    std::string given_name; 
}; 
auto as_tuple(const name_entry& e) 
{ 
    return std::tie(e.family_name, e.given_name); 
} 
bool operator<(const name_entry& x, const name_entry& y) 
{ 
    return as_tuple(x) < as_tuple(y); 
} 
bool operator<(const name_entry& x, const std::string& y) 
{ 
    return x.family_name<y; 
} 
bool operator<(const std::string& x, const name_entry& y) 
{ 
    return x<y.family_name; 
} 
int main() 
{ 
    std::set<name_entry, std::less<>> names; 
} 

Гетерогенного сравнение было изобретен дуэлью с найти содержащийся объект, который удовлетворяет частичное сравнение, как найти кого-то есть данная фамилия.

operator[], в другой стороны, будет построить value_type если key не найден, то необходимо применять строгий слабый порядок с этой операцией, таким образом cannt применяться с гетерогенным сравнением

+0

Я предполагаю, что эти 'operator()' должны быть 'operator <'? Во всяком случае, sane 'operator <' реализация вместо выполнения сравнения вручную: 'return std :: tie (x.family_name, x.given_name) ildjarn

+0

@ildjarn yes, Я скопировал эту бумагу с небольшими изменениями. Сейчас отредактирует. Что касается 'std :: tie', я знаю, что лучше, как я уже сказал, я скопировал из этой статьи – Danh

4

coll.find(key) требует только key быть сравнима с фактическим типом ключа, и std::string_view сравнима с std::string. Однако для того, чтобы вставить key в coll, key должен быть конвертируемый в std::string, который не является (неявным образом, в любом случае).

+2

Я верю, что OP спрашивает, почему 'find' был перегружен, чтобы вывести тип, а' ​​operator [] 'не был расширен Точно так же, а не для объяснения ошибки –