2013-04-09 9 views
5

Ho questa funzione piuttosto semplice, ho alcuni valori che devono essere calcolati ma solo una volta e il momento migliore sarebbe in fase di compilazione. Questi valori sono importanti solo all'interno di questa funzione. E 'un buon uso di constexpr o dovrei semplicemente dichiararli const statici?Devo usare constexpr in questo modo?

ps So che la differenza di prestazioni è così piccola da non avere importanza, ma voglio farlo in modo "criptato".

void MainWindow::UpdateDateTimes() 
{ 
// for some dumb reason DateTime only has add seconds method 
    // so we have to calculate the seconds per hour and the number of hours 
    // we do this with static constant values so that the calculations 
    // only happen once. 
    static constexpr const int secsPerHour = 60 * 60; 
    static constexpr const int cdtOffsetHours = -5; 
    static constexpr const int edtOffsetHours = -4; 
    static constexpr const int cetOffsetHours = 2; 
    static constexpr const int cdtOffsetSecs = secsPerHour * cdtOffsetHours; 
    static constexpr const int edtOffsetSecs = secsPerHour * edtOffsetHours; 
    static constexpr const int cetOffsetSecs = secsPerHour * cetOffsetHours; 

    QDateTime time(QDateTime::currentDateTimeUtc()); 

    ui->mTimeLocal->setDateTime(time.toLocalTime()); 

    ui->mTimeCDT->setDateTime(time.addSecs(cdtOffsetSecs)); 
    ui->mTimeEDT->setDateTime(time.addSecs(edtOffsetSecs)); 
    ui->mTimeCET->setDateTime(time.addSecs(cetOffsetSecs)); 
} 
+0

'constexpr' implica' const'. – Xeo

+1

'const int' è sufficiente per ogni, ma' constexpr int' potrebbe essere più esplicito. Per favore non mescolare i due. – ipc

+0

Non è un const int creato e distrutto ogni volta che viene chiamata la funzione, e quindi devono essere fatti anche i calcoli? So che può essere ottimizzato, ma voglio correggerlo così il codice dice esattamente quello che sto insinuando. – EddieV223

risposta

7

L'utilizzo è soddisfacente, se non un po 'prolisso. In questo contesto, constexpr e const significano esattamente la stessa cosa. O uno (o anche entrambi) farà.

Fwiw, std::chrono::hours::period::num sarebbe un altro modo per specificare 60*60 (se si desidera mostrare alcuni C++ 11 cred :-)).

o addirittura si può semplicemente fare:

void MainWindow::UpdateDateTimes() 
{ 
    constexpr std::chrono::seconds cdtOffsetSecs = std::chrono::hours(-5); 
    constexpr std::chrono::seconds edtOffsetSecs = std::chrono::hours(-4); 
    constexpr std::chrono::seconds cetOffsetSecs = std::chrono::hours(2); 

    QDateTime time(QDateTime::currentDateTimeUtc()); 

    ui->mTimeLocal->setDateTime(time.toLocalTime()); 

    ui->mTimeCDT->setDateTime(time.addSecs(cdtOffsetSecs.count())); 
    ui->mTimeEDT->setDateTime(time.addSecs(edtOffsetSecs.count())); 
    ui->mTimeCET->setDateTime(time.addSecs(cetOffsetSecs.count())); 
} 

Inoltre sarei tentato di abbandonare il static. Sul mio sistema viene generato lo stesso codice esatto con o senza static. Tutto sta accadendo in fase di compilazione, quindi non c'è bisogno della semantica di inizializzazione "una sola volta" di static.

Aggiornamento

solo per fare questo cristallino, ho modificato l'esempio originale:

void f(int); 

void UpdateDateTimes() 
{ 
    constexpr std::chrono::seconds cdtOffsetSecs = std::chrono::hours(-5); 
    constexpr std::chrono::seconds edtOffsetSecs = std::chrono::hours(-4); 
    constexpr std::chrono::seconds cetOffsetSecs = std::chrono::hours(2); 

    f(cdtOffsetSecs.count()); 
} 

Compilato con -O1 (ottimizzazioni a malapena abilitati) con clangore ++ e libC++ e l'assemblaggio è :

.globl __Z15UpdateDateTimesv 
    .align 4, 0x90 
__Z15UpdateDateTimesv:     ## @_Z15UpdateDateTimesv 
    .cfi_startproc 
## BB#0: 
    pushq %rbp 
Ltmp2: 
    .cfi_def_cfa_offset 16 
Ltmp3: 
    .cfi_offset %rbp, -16 
    movq %rsp, %rbp 
Ltmp4: 
    .cfi_def_cfa_register %rbp 
    movl $-18000, %edi   ## imm = 0xFFFFFFFFFFFFB9B0 
    popq %rbp 
    jmp __Z1fi     ## TAILCALL 
    .cfi_endproc 

poi ho compilato questo programma con le stesse impostazioni:

01.235.
void UpdateDateTimes2() 
{ 
    f(-18000); 
} 

e l'Assemblea generato è:

.globl __Z16UpdateDateTimes2v 
    .align 4, 0x90 
__Z16UpdateDateTimes2v:     ## @_Z16UpdateDateTimes2v 
    .cfi_startproc 
## BB#0: 
    pushq %rbp 
Ltmp7: 
    .cfi_def_cfa_offset 16 
Ltmp8: 
    .cfi_offset %rbp, -16 
    movq %rsp, %rbp 
Ltmp9: 
    .cfi_def_cfa_register %rbp 
    movl $-18000, %edi   ## imm = 0xFFFFFFFFFFFFB9B0 
    popq %rbp 
    jmp __Z1fi     ## TAILCALL 
    .cfi_endproc 

Quindi secondo me questo è quanto di più vicino come si arriva mai a un free lunch. :-)