Este é o código do código da biblioteca padrão C ++ remove
. Por que a desigualdade é testada em if (!(*first == val))
vez de if (*first != val)
?
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator result = first;
while (first!=last) {
if (!(*first == val)) {
*result = *first;
++result;
}
++first;
}
return result;
}
operator!=
. Basta usar aoperator==
implementação:bool operator!=(const Foo& other) { return !(*this == other); }
operator==
é uma espécie de espera para ser usado aqui ...const
exemplo no meu comentário anterior, mas você entendeu. (Tarde demais para editá-lo)EqualityComparable
que Hurkyl mencionou em sua resposta .Respostas:
Porque isso significa que o único requisito em T é implementar um
operator==
. Você pode exigir que T tenha uma,operator!=
mas a idéia geral aqui é que você deve colocar o mínimo de carga possível sobre o usuário do modelo e outros modelos precisamoperator==
.fonte
x != y
não está definido para ser o mesmo que!(x == y)
. E se esses operadores retornarem a árvore de análise de uma DSL incorporada?!=
é suportado (retornaria incorretamente verdadeiro - mesmo queoperator==
não seja suportado!). Também estou preocupado que isso faça com que alguns usos!=
se tornem ambíguos.A maioria das funções no STL funciona apenas com
operator<
ouoperator==
. Isso requer que o usuário implemente apenas esses dois operadores (ou às vezes pelo menos um deles). Por exemplo,std::set
usaoperator<
(mais precisamente ostd::less
que chamaoperator<
por padrão) e nãooperator>
para gerenciar pedidos. Oremove
modelo no seu exemplo é um caso semelhante - ele usa apenasoperator==
e não,operator!=
portantooperator!=
, não precisa ser definido.fonte
operator<
diretamente, mas simstd::less
, que, por sua vez, é padronizado comooperator<
.std::set
, por exemplo , realmente usamoperator<
diretamente. Estranho ...std::equal_to
, elas usamoperator==
conforme observado na pergunta. A situação comstd::less
é semelhante. Bem, talvezstd::set
não seja o melhor exemplo.std::equal_to
estd::less
são usados como parâmetros padrão do modelo em que o comparador é usado como parâmetro.operator==
eoperator<
são usados diretamente quando o tipo é necessário para satisfazer a igualdade de ordens comparáveis e estritas, respectivamente, por exemplo, iteradores e iteradores de acesso aleatório.Errado. Não é o
remove
código de biblioteca padrão do C ++ . É uma possível implementação interna daremove
função de biblioteca padrão C ++ . O padrão C ++ não prescreve código real; prescreve protótipos de função e comportamentos necessários.Em outras palavras: Do ponto de vista estrito do idioma, o código que você está vendo não existe . Pode ser de algum arquivo de cabeçalho que acompanha a implementação da biblioteca padrão do seu compilador. Observe que o padrão C ++ nem exige que esses arquivos de cabeçalho existam. Os arquivos são apenas uma maneira conveniente para os implementadores de compiladores atenderem aos requisitos de uma linha como
#include <algorithm>
(por exemplo, disponibilizaçãostd::remove
e outras funções).Porque somente
operator==
é requerido pela função.Quando se trata de sobrecarga de operador para tipos personalizados, o idioma permite que você faça todos os tipos de coisas estranhas. Você pode muito bem criar uma classe que tenha uma sobrecarga,
operator==
mas não sobrecarregadaoperator!=
. Ou pior: você pode sobrecarregar,operator!=
mas fazer com que coisas completamente não relacionadas.Considere este exemplo:
Se
std::remove
usadooperator!=
, o resultado seria bem diferente.fonte
a==b
ea!=b
retornar falso. Embora nem sempre seja claro se tal situação seria considerada de maneira mais significativa como "igual" ou "não igual", uma função que define igualdade apenas em termos do operador "==" deve considerá-los como "não iguais" ", independentemente de qual comportamento faria mais sentido [se eu tivesse meus controladores, todos os tipos devem fazer com que os operadores" == "e"! = "com rendimento booleano se comportem de maneira consistente, mas o fato de o IEEE-754 exigir igualdade de direitos operadores dificultariam tal expectativa].==
e!=
se comporta de maneira consistente, embora eu sempre tenha pensado que todas as seis relações deveriam avaliarfalse
quando pelo menos um operando éNaN
.Algumas boas respostas aqui. Eu só queria adicionar uma pequena nota.
Como todas as boas bibliotecas, a biblioteca padrão é projetada com (pelo menos) dois princípios muito importantes em mente:
Coloque a menor quantidade de responsabilidade nos usuários da sua biblioteca com a qual você pode se safar. Parte disso tem a ver com oferecer o menor trabalho possível ao usar sua interface. (como definir o menor número possível de operadores). A outra parte tem a ver com não surpreendê-los ou exigir que eles verifiquem códigos de erro (portanto, mantenha as interfaces consistentes e crie exceções
<stdexcept>
quando as coisas dão errado).Elimine toda redundância lógica . Todas as comparações podem ser deduzidas apenas a partir de
operator<
, então por que exigir que os usuários definam outras? por exemplo:(a> b) é equivalente a (b <a)
(a> = b) é equivalente a! (a <b)
(a == b) é equivalente a! ((a <b) || (b <a))
e assim por diante.
Obviamente, nesta nota, pode-se perguntar por que
unordered_map
requeroperator==
(pelo menos por padrão) e nãooperator<
. A resposta é que, em uma tabela de hash, a única comparação que exigimos é a igualdade. Portanto, é mais logicamente consistente (isto é, faz mais sentido para o usuário da biblioteca) exigir que ele defina um operador de igualdade. Exigir umoperator<
seria confuso, porque não é imediatamente óbvio por que você precisaria.fonte
operator==
(ehash
).!(a==b)
. Como a sobrecarga não refletida de operadores pode facilmente fazer com que o programa C ++ fique completamente confuso (além disso, enlouquece o programador porque a depuração de seu código pode se tornar uma missão impossível, pois encontrar o culpado de um bug específico é semelhante a uma odisseia).!((a < b) || (b < a))
usa menos um operador booleano, por isso é provavelmente mais rápidoO
EqualityComparable
conceito requer apenas queoperator==
seja definido.Conseqüentemente, qualquer função que professa trabalhar com tipos satisfatórios
EqualityComparable
não pode contar com a existência deoperator!=
objetos desse tipo. (a menos que haja requisitos adicionais que impliquem a existência deoperator!=
).fonte
Do Boost FAQ: fonte
Sabendo que exigir uma
==
implementação é um fardo , você nunca deseja criar um ônus adicional ao exigir também a!=
implementação.Para mim, pessoalmente, é sobre o SOLID (projeto orientado a objetos) L parte - princípio de substituição de Liskov: "os objetos em um programa devem ser substituíveis por instâncias de seus subtipos sem alterar a correção desse programa". Nesse caso, é o operador ! = Que eu posso substituir por == e booleano inverso na lógica booleana.
fonte