Posso alterar a precedência e a associatividade do operador em C ++?

4

Como o título diz, acho útil sobrecarregar os operadores. É possível também alterar a maneira como os operadores são analisados, especificando a precedência e a associatividade dos operadores substituídos?

    
por user827992 16.08.2012 / 06:55
fonte

4 respostas

17

Não, você não pode fazer isso e isso é bom. A sobrecarga do operador já tem potencial suficiente para tornar o código ilegível sem poder alterar a precedência ou a associatividade.

Se você quiser fazer isso, você provavelmente está abusando da sobrecarga do operador e deve usar funções normais.

    
por 16.08.2012 / 21:36
fonte
14

Não. Além de tornar o código ilegível, isso tornaria a linguagem mais ambígua e profundamente dependente do contexto, porque você não seria capaz de associar parâmetros a chamadas de função até conhecer todos os operadores disponíveis.

Considere a expressão

a1 + a2 * a3

em que todos os a* vars têm o tipo A e você tem sobrecargas

A operator+(A, A) // low precedence
A operator*(A, A) // high precedence
B operator+(A, A) // high precedence
A operator*(B, A) // low precedence

Isso poderia ser interpretado de duas maneiras diferentes

operator+(a1, operator*(a2, a3))

ou

operator*(operator+(a1, a2), a3)

Com regras de precedência global e associatividade, o compilador pode se comprometer com a primeira interpretação durante a análise, mas com associatividade / precedência substituível, não há como descobrir como decompor tokens em chamadas de função até conhecer todas as assinaturas de operador disponíveis.

Isso não torna a linguagem impossível de ser analisada (embora haja mais programas que precisam ser rejeitados como não tipificáveis), mas seria mais lento compilar e mais difícil de ler.

    
por 16.08.2012 / 22:49
fonte
5

Não. Embora possa parecer à primeira vista que faz sentido, se você pensar um pouco mais, torna-se enlameado a ponto de ser uma má ideia.

Primeiro, observe que a linguagem não é definida usando uma gramática de precedência, mas uma BNF mais clássica. Não tenho certeza se o comportamento de sizeof ou ?: é descritível simplesmente com uma noção de prioridade e associatividade.

Mas a questão principal é que você está mudando a prioridade e a associatividade de operadores sobrecarregados , não definindo a prioridade e a associatividade de novos operadores usados apenas para os seus tipos. Você quer que suas alterações sejam aplicáveis para todos os usos, ou apenas para sua sobrecarga? Você provavelmente concordará que a primeira opção é uma receita certa para problemas. O outro não é muito melhor. Como você sabe que é a sua sobrecarga que deve ser considerada antes de fazer a resolução de sobrecarga, que precisa de análise e, portanto, associatividade e prioridade para ser conhecido.

    
por 16.08.2012 / 21:51
fonte
5

Depois de ler algumas das respostas, acho que sim, é hora de eu procurar por votos negativos.

  • O << representa o deslocamento de bits com std::ostream ?
  • O + representa uma adição aritmética com std::string ?
  • O * representa o cancelamento de referência em boost::spirit ?

Apesar deste fato bem estabelecido, ainda existem pessoas afirmando que o operador de sobrecarga torna o código ilegível e, portanto, você não deve ... blá blá ... e elas não devem. .. blah blah ... e permitindo mudar precedência .

Acho esses argumentos simplesmente incoerentes.

Operadores são o que faz a entidade formar uma expressão que, em conjunto, define uma álgebra. Se uma entidade não é numérica, não há necessidade (quero dizer, necessidade matemática) de que tal álgebra tenha que seguir a mesma regra dos números naturais.

Uma das razões pela qual os operadores sobrecarregados tornam o código difícil de ler é apenas porque eles estão restritos a permanecer nas regras semânticas int, mesmo para coisas que não têm semântica inteira e, portanto, não precisam dessa mesma sintaxe.

A resposta para a pergunta é:

NÃO : não é possível alterar a precedência porque a especificação de idioma não permite isso. Ponto final.

E se você quiser saber o porquê, você tem que olhar para o que a linguagem é.

O C ++ já é uma linguagem complexa para analisar e traduzir.  Ao admitir "operadores flexíveis" (ou mesmo a definição de funções infreqüenciais arbitrárias, como ** , <> , <-> , etc), o analisador de expressão não pode mais ser implementado além de tipos, e isso foi argumentado pelo designer de linguagem como um "recurso com tradeoff negativo" (custa mais ser implantado que a vantagem que ele jamais dará no mundo real). É apenas "echonomy", não "moralidade".

Todo o aspecto "moral" (não faça isso porque me machuca) não tem nada a ver com o idioma e o abuso do operador (posso até abusar de for e usá-lo em vez de if , mas o problema é eu, não a palavra-chave for , não faz sentido, pois não faz sentido basear a precedência variável mesmo sem saber o uso correto dela, pela simples razão de que não pode haver um uso - não importa se é ruim ou bom - sendo tal coisa proibida na origem.) e estão relacionados apenas ao marketing de linguagem.

A sobrecarga do operador C ++ foi introduzida para permitir que os cientistas definam tipos algébricos privados. É normal que eles peçam mais flexibilidade na definição e uso de símbolos.

A linguagem Java foi definida para padronizar a codificação em torno da OOP. E como nem todos os programadores aspirantes são também pesquisadores científicos, o Java removeu uma série de recursos que podem fazer com que a linguagem se desvie do paradigma OOP em que foi filosoficamente projetado. E para motivar isso para novatos, uma religião dogmática alegando "operador considerado prejudicial", "variáveis globais consideradas prejudiciais" e assim por diante foi formalizada e implantada em todas as escolas.

E o bash contra certas práticas de codificação perfeitamente comuns em matemática e ciência começou apenas a partir daí.

É muito simples ensinar "não porque é ruim e faz você ir para o inferno" em vez de fornecer e comparar idéias racionais. E o resultado - 20 anos depois - é que, se você fizer isso, você realmente vai para o inferno porque todos aqueles que acreditam na religião (que hoje em dia são uma enorme quantidade de pessoas) tornarão sua vida impossível.

E como Java se tornou o primeiro idioma, novatos são expostos (e C ++, eventualmente, um segundo) e seus paradigmas são ensinados como dogmas aos alunos. Quando esses estudantes se tornam programadores, eles acabam aplicando esses "dogmas" a qualquer coisa. ".

Afinal, ninguém pode dar uma razão racional sobre seu time de futebol favorito. acontece quando você começa a segui-lo. Não há "razões técnicas". Apenas paixão (dogmas) e o estresse para mudar (métodos OOP forçados até mesmo fora do contexto OOP)

A razão pela qual você não pode mudar a precedência é simplesmente que o mundo mantém que mudar esse dogma causará muito estresse a muitos crentes. Mas racionalmente falando, não há razão para você acreditar de maneira diferente e fazer com que você defina uma linguagem com mais liberdade de uso.

    
por 07.04.2014 / 09:19
fonte

Tags