2013-09-26 11 views
7

Lo standard C++ 11 specifica un tratto di tipo std::alignment_of<T> che restituisce semplicemente il valore di alignof(T).Tipo di carattere standard per il valore di sizeof (T)

C'è una caratteristica simile per l'operatore sizeof? Mi manca o è mancato lo standard, o c'è qualche oscuro motivo tecnico per cui non è stato specificato?

Ovviamente è banale creare un tale tratto, ma non posso immaginare che non sarebbe stato preso in considerazione quando si introduce std::alignment_of.

per il contesto, ho un tipo personalizzato tratto che io uso per ottenere il valore massimo di un singolo tratto se applicato a un elenco dei tipi.

template <template<class> class Trait, typename F, typename... T> 
struct trait_max 
    : std::integral_constant<decltype(Trait<F>::value), 
     (Trait<F>::value > trait_max<Trait, T...>::value) ? Trait<F>::value : trait_max<Trait, T...>::value> 
{ }; 
template <template<class> class Trait, typename F> 
struct trait_max<Trait, F> 
    : std::integral_constant<decltype(Trait<F>::value), Trait<F>::value> 
{ }; 

Questa caratteristica è veramente a portata di mano per quando avete bisogno di conoscere il massimo di un insieme di tipi in questo modo:

auto max_align = traits_max<std::alignment_of, int, float, std::string>::value; 
auto max_size = traits_max<std::size_of, int, float, std::string>::value; // doesn't exist 
+1

Typo nel codice, '' Trait dovrebbe essere '' Trait dopo che l'operatore '?'. Ho notato solo perché è fantastico, e lo sto usando così. –

+2

Il motivo unico 'std :: alignment_of ' è nella norma è perché era parte di TR1. – Simple

+2

Fortunatamente, 'modello struct size_of: std :: integral_constant {};' non è difficile neanche scrivere. – Yakk

risposta

3

std::alignment_of non è nuovo in C++ 11. E 'stato aggiunto (insieme al resto della <type_traits>) come parte di TR1 nel 2007. all'ingrosso <type_traits> è stato copiato di TR1 da Boost TypeTraits, che ha fornito alignment_of solo perché non c'era modo standard per arrivare a quel valore nel 2005.

Naturalmente nel 2005 ci fu un modo per ottenere la dimensione di un tipo T; è stato scritto sizeof(T) da tempo immemorabile. Ecco perché size_of<T> non era in Boost TypeTraits, e è perché non è stato copiato in TR1 nel 2007 e è perché non era grandfathering in C++ 11.

A partire dal 2011, c'è anche un modo standard per ottenere l'allineamento di un tipo T; è scritto alignof(T). Il pre-2011 costrutto std::alignment_of<T>::value è inutilmente prolisso, e quasi certamente non dovrebbe usare faccio più a meno che non siete preoccupati per la portabilità di pre-2011 implementazioni.

Credo che il modo più idiomatico di scrittura del codice di esempio è

size_t max_align = std::max({alignof(int), alignof(float), alignof(std::string)}); 
size_t max_size = std::max({sizeof(int), sizeof(float), sizeof(std::string)}); 

Una volta che C++ 14 rotoli in giro, std::max diventerà constexpr, quindi questo sarà calcolato al momento della compilazione e utilizzati in template metaprogrammazione. Ma il risucchio di C++ 11 std::max è un problema completamente separato, non correlato alla tua domanda. :)

MODIFICA: Ecco un constexpr_max che funziona nel C++ 11 di oggi. Sfortunatamente il std::initializer_list di C++ 11 non può essere utilizzato in un contesto constexpr; C++ 14 sta risolvendo anche quello.

template<typename T> constexpr T constexpr_max(T t, T u) { 
    return t > u ? t : u; 
} 

template<typename T, typename... TT> constexpr T constexpr_max(T t, TT... ts) { 
    return constexpr_max(t, constexpr_max(ts...)); 
} 
+0

Sto usando questo tratto nel modello metaprogrammazione, in modo che i tipi nel codice di esempio vengono normalmente upacked da un modello variadic. Simile al tuo suggerimento, 'std :: max ({sizeof (T) ...});' sarebbe perfetto, ma senza 'constexpr' su' std :: max' sono costretto a ricorrere a un tratto personalizzato. Credo di essere sorpreso questo non è venuto durante la standardizzazione. Se 'alignment_of' era considerato inutile in un mondo' alignof', perché non svalutarlo? Se fosse ancora utile, perché non aggiungere l'analogo 'size_of'? Uno dei piccoli misteri della vita ... – marack

+0

Bene, sei obbligato a ricorrere a "un tratto personalizzato" * o * a una funzione constexpr 'max' personalizzata, che hai già scritto, se togli semplicemente il' trait_' cruft dal tuo 'trait_max'. :) aggiornerò la mia risposta con un codice di esempio. – Quuxplusone

+0

Molto bello. Grazie! – marack

Problemi correlati