2014-09-18 17 views
6

In this comment to another question, l'HVD utente indicato quanto segue:Gli array possono essere indicizzati al momento della compilazione?

... sebbene stringhe possono essere passati alle funzioni constexpr, e matrice indicizzazione è accettati letterali stringa in costante espressioni, un'operazione di avanzamento intermittente su una Il parametro constexpr della funzione non si qualifica come espressione costante.

Non ho capito completamente cosa si intendesse. Vuol dire che la variabile hash_value nel codice seguente

#include <cstddef> 

// Compute the hash of a string literal adding the values of its characters 
template<std::size_t N> constexpr std::size_t 
hash_string 
    (const char (& s)[N]) 
noexcept 
{ 
    std::size_t h = 0; 

    // Array indexing happening under the hood 
    for (const auto c : s) 
     h += c; 

    return h; 
} 

constexpr auto hash_value = hash_string("Hello, world!"); 

non può essere valutato al momento della compilazione? Potresti approfondire il commento citato e dire se ho ragione?

+0

Non vedo nulla in C++ 14 standard che vieti questo. Il tuo codice compila bene in clang. –

+0

Molti compilatori fanno questo tipo di ottimizzazione? Sembra molto aggressivo. – tadman

+0

@ T.C. Sì, compila e funziona anche per me su Clang. Tuttavia, e soprattutto dal momento che non conosco il montaggio, voglio assicurarmi che venga valutato al momento della compilazione. – Kalrish

risposta

3

Quello che dicevo in quel commento era che non si può avere qualcosa di simile

template <int N> 
int f(); 

constexpr int g(int i) { 
    return f<i>(); // invalid 
} 

perché anche se il risultato di una funzione constexpr può essere un'espressione costante, all'interno del corpo, i suoi parametri non sono. Una funzione constexpr può essere chiamata con argomenti costanti o non costanti, il chiamante deve decidere e C++ non ha alcun tipo di funzione che può solo essere chiamato con argomenti costanti.

Era importante nella risposta che stavi leggendo perché sarebbe stato utile avere un argomento di funzione const char (&str)[N] e trattare str[i] come espressione costante all'interno del corpo della funzione.

Questo non ha importanza per il codice che hai. Quel codice va bene.

+0

Grazie! Ora lo capisco: una funzione 'constexpr' è _enabled_ da valutare al momento della compilazione, ma non _required_. Pertanto, può essere utilizzato in un contesto in cui sono richieste le espressioni costanti, ma non può essere assunto che verrà sempre eseguito in fase di compilazione. Ecco perché gli argomenti della funzione 'constexpr' non possono essere valutati in un' static_assert'. – Kalrish

+0

+1 (da ieri) grazie per aver seguito e chiarito. –

2

sono andato attraverso le sezioni pertinenti sia N3337 e N3936, e nulla in entrambe le versioni dello standard vieta una funzione constexpr del genere

template<std::size_t N> constexpr std::size_t 
hash_string 
    (const char (& s)[N]) 
noexcept 
{ 
    return s[0]; 
} 

E in effetti questo compila sia g ++ e clang in C++ 11 modalità. Non ho assolutamente idea di dove sia arrivata l'affermazione secondo cui "un'operazione di indicizzazione su un parametro di funzione constexpr non si qualifica come un'espressione costante". Non riesco a trovare nulla in §5.19 [expr.const] che vieta questo.

+0

Il problema può derivare dall'uso del ciclo 'for'? –

+0

@RSahu Questo è un problema di C++ 14 vs. C++ 11. Il ciclo non è ammesso in C++ 11 'constexpr', ma la dichiarazione di indicizzazione non è correlata a questo. –

+0

@hvd Vorrei ancora conoscere i motivi della dichiarazione citata, anche dopo la spiegazione basata su standard. Mi incuriosisce :). – Kalrish

Problemi correlati