Se houver, std::map<std::pair<std::string, std::string>, some_type>
qual é a melhor maneira de encontrar seus valores?
Acho que o mais óbvio é fazer algo assim:
map.find(std::make_pair(str1, str2));
mas isso levará a uma construção de cópia das strings str1
e str2
durante a construção do par.
Eu esperava que talvez map.find(std::make_pair(std::ref(str1), std::ref(str2)));
pudesse ajudar, mas infelizmente não, isso ainda produz cópias de strings.
map.find(std::make_pair(std::move(str1), std::move(str2))
deve funcionar, mas vamos supor que essas strings ( str1
, str2
) sejam const ou não devam ser movidas.
Então, estou perguntando se existe alguma outra maneira de fazer uma pesquisa no mapa sem fazer cópias redundantes de strings.
(Observe que usar std::string_view
for the std::map key
NÃO é uma opção, pois o mapa deve possuir suas strings.)
C++ 14 adicionou a seguinte sobrecarga para
std::map::find
a qual permite pesquisa transparente:Para fazer uso disso, você ainda precisa
std::map
ter um comparador adequado:Isto
pair_less
é totalmente transparente. Ele pode ser comparado diretamentestd::pair<X, Y>
comstd::pair<const X&, const Y&>
.Nota sobre
std::pair::operator<
O padrão C++ exige
std::pair::operator<
ser transparente desde LWG Defect 3865 . Teoricamente, isso seriastd::less<void>
suficientestd::ranges::less
como um comparador transparente.No entanto, libstdc++ ainda não implementa
std::pair
comparações transparentes no momento da escrita, portantostd::less<void>
funcionaria apenas para compiladores diferentes do GCC.Restrições adequadas do C++ 20
Restringir adequadamente o operador de chamada
pair_less
não é tão fácil. De qualquer forma, não é estritamente necessário, mas move o erro para o local de chamada da operadora e pode ser melhor para diagnóstico.A abordagem usual seria algo como
Veja também
boolean-testable
.Para evitar a construção de chave, você pode usar
std::map
um comparador transparente. Em muitos casos, você não precisa implementar o seu próprio - o padrão fornecestd::less<>
isso para fazer o trabalho.Infelizmente, não funcionará com
std::pair
chaves porquestd::pair
faltam comparações heterogêneas : você não pode compararstd::pair<std::string, std::string>
comstd::pair<const std::string&, const std::string&>
.Mas se você pudesse mudar
std::pair
parastd::tuple
, funcionaria:Mesmo que você não possa ter
std::string_view
chaves, você ainda pode usarstd::string_view
para seu comparador (já que você pode converter facilmente umstd::string
->std::string_view
):std::tuple
foi usado em vez destd::pair
porque você pode converterpair
->tuple
, mas não o contrário. Isso significa que você também pode usar teclas de tupla, que possuem funções úteis de fábrica:Dois
compare
s foram usados em vez del < r
porque as tuplas anteriores ao C++ 20operator<
resultariam em trêsmemcmp
s em vez de dois (l[0] < r[0]; r[0] < l[0]; l[1] < r[1]
. Eles não parecem estar otimizados).