O que exatamente é a regra do “como se”?

Como o título diz

O que exatamente é a regra “como se”?

Uma resposta típica que alguém obteria é:

A regra que permite todas e quaisquer transformações de código que não alteram o comportamento observável do programa

De tempos em tempos, continuamos adquirindo comportamentos de certas implementações que são atribuídas a essa regra. Muitas vezes erradamente. Então, o que exatamente é essa regra. A norma não menciona claramente esta regra como uma seção ou parágrafo, então o que exatamente está sob a alçada desta regra? Para mim, parece uma área cinza que não é definida em detalhes pelo padrão. Alguém pode elaborar os detalhes citando as referências do padrão.

Nota: Marcando isto como C e C ++, porque é relevante para ambos os idiomas.

Qual é a regra ” como se “?

A regra ” como se ” basicamente define quais transformações uma implementação pode executar em um programa C ++ legal. Em resumo, todas as transformações que não afetam o ” comportamento observável ” de um programa (veja abaixo uma definição precisa) são permitidas.

O objective é dar às implementações liberdade para executar otimizações, desde que o comportamento do programa permaneça compatível com a semântica especificada pelo Padrão C ++ em termos de uma máquina abstrata.


Onde o Padrão introduz esta regra?

O C ++ 11 Standard introduz a regra ” como se ” no Parágrafo 1.9 / 1:

As descrições semânticas nesta Norma definem uma máquina abstrata não determinística parametrizada. Este Padrão Internacional não impõe nenhuma exigência na estrutura de implementações em conformidade. Em particular, eles não precisam copiar ou emular a estrutura da máquina abstrata. Em vez disso, é necessário que as implementações em conformidade imitem (apenas) o comportamento observável da máquina abstrata, conforme explicado abaixo.

Além disso, uma nota de rodapé explicativa acrescenta:

Esta provisão é às vezes chamada de regra “como se” , porque uma implementação é livre para desconsiderar qualquer exigência desta Norma desde que o resultado seja como se a exigência tivesse sido obedecida, tanto quanto possível a partir do comportamento observável. do programa. Por exemplo, uma implementação real não precisa avaliar parte de uma expressão se puder deduzir que seu valor não é usado e que nenhum efeito colateral que afete o comportamento observável do programa é produzido.


O que a regra exige exatamente?

O parágrafo 1.9 / 5 especifica ainda:

Uma implementação em conformidade executando um programa bem formado deve produzir o mesmo comportamento observável de uma das possíveis execuções da instância correspondente da máquina abstrata com o mesmo programa e a mesma input . No entanto, se tal execução contiver uma operação indefinida, esta Norma não coloca nenhum requisito na implementação que executa aquele programa com essa input (nem mesmo com relação às operações que precedem a primeira operação indefinida).

Vale a pena ressaltar que essa restrição se aplica apenas quando “executar um programa bem formado” e que os resultados possíveis da execução de um programa que contém um comportamento indefinido são irrestritos. Isso é explicitado no parágrafo 1.9 / 4 também:

Certas outras operações são descritas nesta Norma como indefinida (por exemplo, o efeito de tentar modificar um object const). [Nota: Esta Norma não impõe requisitos sobre o comportamento de programas que contenham comportamento indefinido . – end note]

Finalmente, no que diz respeito à definição de ” comportamento observável “, o parágrafo 1.9 / 8 é o seguinte:

Os requisitos mínimos em uma implementação em conformidade são:

– O access a objects voláteis é avaliado estritamente de acordo com as regras da máquina abstrata.

– No término do programa, todos os dados gravados em arquivos devem ser idênticos a um dos possíveis resultados que a execução do programa de acordo com a semântica abstrata teria produzido.

– A dinâmica de input e saída de dispositivos interativos deve ocorrer de tal forma que a saída de prompts seja realmente entregue antes que um programa espere pela input. O que constitui um dispositivo interativo é definido pela implementação.

Estes coletivamente são referidos como o comportamento observável do programa . [ Nota : Correspondências mais rigorosas entre a semântica abstrata e real podem ser definidas por cada implementação. – nota final


Existem situações em que esta regra não se aplica?

Tanto quanto sei, a única exceção à regra do ” como-se ” é a elisão copy / move, que é permitida mesmo que o construtor de cópia, o construtor de movimento ou o destruidor de uma class tenham efeitos colaterais. As condições exatas para isso são especificadas no Parágrafo 12.8 / 31:

Quando determinados critérios são atendidos, uma implementação pode omitir a construção copiar / mover de um object de class, mesmo que o construtor selecionado para a operação de copiar / mover e / ou o destruidor do object tenha efeitos colaterais . […]

Em C11, a regra nunca é chamada por esse nome. No entanto, C, assim como o C ++, define o comportamento em termos de máquina abstrata. A regra como-se está em C11 5.1.2.3p6 :

  1. Os requisitos mínimos em uma implementação em conformidade são:

    • Acessos a objects volatile são avaliados estritamente de acordo com as regras da máquina abstrata.
    • No término do programa, todos os dados gravados em arquivos devem ser idênticos ao resultado que a execução do programa de acordo com a semântica abstrata teria produzido.
    • A dinâmica de input e saída dos dispositivos interativos deve ocorrer conforme especificado em 7.21.3 . A intenção desses requisitos é que a saída sem buffer ou com buffer de linha apareça o mais rápido possível, para garantir que as mensagens solicitantes realmente apareçam antes de um programa aguardar a input.

    Este é o comportamento observável do programa.