Qual è esattamente la regola “as-if”?

Come dice il titolo,

Qual è esattamente la regola “as-if”?

Una tipica risposta che si potrebbe ottenere è:

La regola che consente tutte le trasformazioni di codice che non modificano il comportamento osservabile del programma

Di tanto in tanto continuiamo a ricevere comportamenti da alcune implementazioni attribuite a questa regola. Molte volte erroneamente. Quindi, qual è esattamente questa regola. Lo standard non menziona chiaramente questa regola come una sezione o un paragrafo, quindi cosa rientra esattamente nel campo di applicazione di questa regola? Per me sembra un’area grigia che non è definita in dettaglio dallo standard. Qualcuno può elaborare i dettagli citando i riferimenti dallo standard.

Nota: taggare questo come C e C ++ entrambi, perché è rilevante per entrambe le lingue.

Qual è la regola ” as-if “?

La regola ” as-if ” definisce fondamentalmente quali trasformazioni un’implementazione è autorizzata ad eseguire su un programma C ++ legale. In breve, tutte le trasformazioni che non influenzano il ” comportamento osservabile ” di un programma (vedi sotto per una definizione precisa) sono permesse.

L’objective è dare alle implementazioni la libertà di eseguire ottimizzazioni finché il comportamento del programma rimane conforms alla semantica specificata dallo standard C ++ in termini di una macchina astratta.


Dove lo standard introduce questa regola?

Lo standard C ++ 11 introduce la regola ” as-if ” nel Paragrafo 1.9 / 1:

Le descrizioni semantiche di questo standard internazionale definiscono una macchina astratta non parametrica parametrizzata. Questo standard internazionale non impone alcun requisito sulla struttura delle implementazioni conformi. In particolare, non è necessario copiare o emulare la struttura della macchina astratta. Piuttosto, sono necessarie implementazioni conformi per emulare (solo) il comportamento osservabile della macchina astratta come spiegato di seguito.

Inoltre, una nota esplicativa aggiunge:

Questa disposizione viene talvolta chiamata la regola “as-if” , poiché un’implementazione è libera di ignorare qualsiasi requisito di questo Standard Internazionale finché il risultato è come se il requisito fosse stato rispettato, per quanto è ansible determinare dal comportamento osservabile del programma. Ad esempio, un’implementazione effettiva non deve valutare parte di un’espressione se può dedurre che il suo valore non è usato e che non vengono prodotti effetti collaterali che influenzano il comportamento osservabile del programma.


Che cosa regola esattamente la regola?

Il paragrafo 1.9 / 5 specifica inoltre:

Un’implementazione conforms che esegue un programma ben formato deve produrre lo stesso comportamento osservabile di una delle possibili esecuzioni dell’istanza corrispondente della macchina astratta con lo stesso programma e lo stesso input . Tuttavia, se una qualsiasi esecuzione di questo tipo contiene un’operazione non definita, questo Standard Internazionale non pone alcun requisito sull’implementazione che esegue quel programma con quell’input (nemmeno per quanto riguarda le operazioni che precedono la prima operazione non definita).

Vale la pena sottolineare che questo vincolo si applica solo quando “esegue un programma ben formato” e che i possibili esiti dell’esecuzione di un programma che contiene un comportamento non definito non sono vincolati. Ciò è esplicitato anche al paragrafo 1.9 / 4:

Alcune altre operazioni sono descritte in questo standard internazionale come non definite (ad esempio, l’effetto del tentativo di modificare un object const). [Nota: questo Standard Internazionale non impone alcun requisito sul comportamento di programmi che contengono comportamenti non definiti . -End note]

Infine, riguardo alla definizione di ” comportamento osservabile “, il paragrafo 1.9 / 8 è il seguente:

I requisiti minimi per un’implementazione conforms sono:

– L’accesso agli oggetti volatili viene valutato rigorosamente secondo le regole della macchina astratta.

– Al termine del programma, tutti i dati scritti nei file devono essere identici a uno dei possibili risultati che l’esecuzione del programma secondo la semantica astratta avrebbe prodotto.

– La dynamic di input e output dei dispositivi interattivi deve avvenire in modo tale che l’output di prompt venga effettivamente consegnato prima che un programma attenda l’input. Ciò che costituisce un dispositivo interattivo è definito dall’implementazione.

Questi collettivamente sono indicati come il comportamento osservabile del programma . [ Nota : corrispondenze più stringenti tra semantica astratta e reale possono essere definite da ciascuna implementazione. – nota finale ]


Ci sono situazioni in cui questa regola non si applica?

Per quanto ne so, l’unica eccezione alla regola ” as-if ” è copia / sposta elision, che è consentita anche se il costruttore di copia, il costruttore di movimento o il distruttore di una class hanno effetti collaterali. Le condizioni esatte per questo sono specificate nel paragrafo 12.8 / 31:

Quando vengono soddisfatti determinati criteri, a un’implementazione è consentito omettere la costruzione di copia / spostamento di un object di class, anche se il costruttore selezionato per l’operazione di copia / spostamento e / o il distruttore per l’object hanno effetti collaterali . […]

In C11 la regola non viene mai chiamata con quel nome. Tuttavia C, proprio come C ++, definisce il comportamento in termini di macchina astratta. La regola as-if è in C11 5.1.2.3p6 :

  1. I requisiti minimi per un’implementazione conforms sono:

    • Gli accessi agli oggetti volatile vengono valutati rigorosamente in base alle regole della macchina astratta.
    • Al termine del programma, tutti i dati scritti nei file devono essere identici al risultato che l’esecuzione del programma in base alla semantica astratta avrebbe prodotto.
    • Le dinamiche di input e output dei dispositivi interattivi devono avere luogo come specificato in 7.21.3 . Lo scopo di questi requisiti è che l’output non bufferizzato o con buffer di linea compaia il prima ansible, per garantire che i messaggi di richiesta vengano effettivamente visualizzati prima di un programma in attesa di input.

    Questo è il comportamento osservabile del programma.