2015-04-01 7 views
5

Il seguente codice:Perché le cifre10 sono utilizzate come riferimento per il numero intero di tipo 0?

#include <iostream> 
#include <limits> 
#include <cstdint> 

int main() 
{ 
    std::cout << std::numeric_limits<std::uint64_t>::digits10 << "\n" 
       << std::numeric_limits<std::uint64_t&>::digits10 << "\n"; 
} 

uscite

mi aspetterei std::uint64_t& di avere lo stesso valore come std::uint64_t: C'è una ragione di questa discrepanza?

+2

'std :: numeric_limits' non è specializzato su quel tipo, quindi è 0 per impostazione predefinita. – 0x499602D2

+1

dal punto di vista della progettazione linguistica, il valore predefinito non dovrebbe essere un errore di compilazione? –

+2

Nessun motivo specifico: si limitano a fare in modo che i tipi di riferimento abbiano gli stessi valori in 'numeric_limits' in quanto il non riferimento richiede uno sforzo aggiuntivo e nessuno ha pensato di renderlo conveniente per te. Puoi 'std :: remove_reference :: type' se questo ti riguarda. – milleniumbug

risposta

1

Il tipo uint64& è un riferimento, quindi non è uno dei tipi aritmetici per cui è necessario utilizzare il modello numeric_limits.

Per qualsiasi altro tipo rispetto ai tipi aritmetici definiti, la definizione predefinita viene utilizzata contenente:

static const int digits10 = 0; 

Riferimento: http://www.cplusplus.com/reference/limits/numeric_limits/

2

18.3.2.1/2:

specializzazioni membri essere fornito per ogni tipo aritmetico, sia in virgola mobile che intero, compreso il bool. Il membro è_specializzato deve essere vero per tutte le specializzazioni di numeric_limits.

Quindi sappiamo che esistono specializzazioni per questi tipi non di riferimento. Quindi 18.3.2.3/1:

Il modello numeric_limits predefinito deve avere tutti i membri, ma con 0 o valori falsi.

ho il sospetto che è stato fatto in questo modo, perché si può sempre static_assert su is_specialized per forzare un errore di compilazione, ma ci potrebbe essere qualche applicazione modello in cui 0 sarebbe un valore predefinito ok per uno o più dei limiti. Se si desidera essere in grado di testare i riferimenti, basta eseguirlo tramite std::remove_reference.

Non sono sicuro che sia legale specializzare numeric_limits per i propri tipi. Lo standard in 18.3.2.1/4 dice:

tipi

non aritmetiche standard, come complessi (26.4.2), non devono avere specializzazioni.

Personalmente leggo questo qute come "lo standard non fornirà specializzazioni per i tipi di libray standard non aritmetici, ma è perfettamente legale specializzarsi per un tipo di utente". Si potrebbe facilmente leggere questo come vietando totalmente qualsiasi specializzazione non fornita.

+0

sembra un errore zoppo, ma per ora questa è la migliore A, se qualcuno non ha una risposta che spieghi il ragionamento che accetterò. :) – NoSenseEtAl

+0

Specializzare 'std :: numeric_limits' per non-aritmetico' T's [non consentito] (https://stackoverflow.com/questions/8513417/what-can-and-cant-i-specialize-in- the-STD-namespace). – edmz

+0

@MarkB Mi riferivo a: "numeric_limits non deve essere specializzato per i tipi standard non aritmetici". Non è possibile specializzarlo nello spazio dei nomi 'std', per quanto ne so (gli altri dovrebbero essere autorizzati btw). O intendevi qualcos'altro? – edmz

0

std::numeric_limits si prevede che sia specializzato per i tipi di dati aritmetici fondamentali (interi e punti mobili). Un riferimento, di qualsiasi tipo, non appartiene a loro ed è per questo che viene scelto il modello non specializzato, che ha tutti i suoi membri a false (0).

mi aspetterei std :: uint64_t & di avere lo stesso valore come std :: uint64_t: è C'è una ragione di questa discrepanza?

Sebbene std::uint64_t è un tipo aritmetico, std::uint64_t& è un tipo di composto e ha un significato diverso. Avete alcune opzioni:

  • Considerare sempre il tipo di base rimuovendo il riferimento, il puntatore o entrambi.
  • static_assert(is_arithmetic<>)
  • controllo std::numeric_limits<T>::is_specialized
Problemi correlati