2016-09-21 2 views
38

Dzisiaj w naszej bazie kodu znaleziono następującą linię i lubiliśmy jej elegancję za pisanie rozmiaru pamięci. Przez kilka minut zastanawiałem się, jak się to kompiluje.Jak napisać stałą literałową, np. "Size_t s = 16 MByte"?

size_t poolSize = 16 MByte; 

Jedno rozwiązanie podano jako moją własną odpowiedź. Jakieś inne rozwiązania?

+3

http://pl.cppreference.com/w/cpp/language/user_literal –

Odpowiedz

81

We współczesnym C++ zalecana define a literal notation, np

auto operator""_MB(unsigned long long const x) 
    -> long 
{ return 1024L*1024L*x; } 

Następnie napisać

long const poolSize = 16_MB; 

Nie używać makr, są Zło ™. Na tak wiele sposobów.


Nota prawna: kod nie został dotknięty rękami kompilatora.

+24

MiB byłby dokładniejszy – TemplateRex

+8

@TemplateRex: Kiedyś argumentowałem, że jakieś 15+ lat temu. Ale te oznaczenia jednostek nigdy się nie przyjęły. Łapiemy się w zamrożonej historii, tak jak w wielu innych sprawach. –

+0

Wygląda na to, że MiB/GiB/TiB czasami wciąż są używane w rozmiarze dysku i pliku. Prawdopodobnie jest to bardziej istotne, ponieważ nie ma mocy o dwóch rozmiarach są powszechne, a ponieważ 1.024^n jest coraz dalej i dalej od 1 z większymi prefiksami. –

5

To było proste i sprytne użycie starych dobrych makr.

#define KByte *1024 
#define MByte *1024*1024 
#define GByte *1024*1024*1024 

Więc size_t poolSize = 16 MByte; dostaje języku

size_t poolSize = 16 *1024*1024; 
+44

To było proste i straszne nadużycie makr. Nigdy tego nie rób. –

+1

Nie używaj do tego preprocesora. Ponieważ programujesz w C++, powinieneś naprawdę używać [litereli definiowanych przez użytkownika] (http://en.cppreference.com/w/cpp/language/user_literal). –

+1

tak, zupełnie nie C++. Ale myślę, że było urocze, gdy kod został napisany 10/15 lat temu. – PermanentGuest

11

Oczywiście należy użyć szablonu metaprogramowanie dla tego problemu:

#include <iostream> 
#include <type_traits> 

template<long long N, long long M> 
struct is_power_of 
{ 
    static constexpr bool value = (N%M != 0)? false : is_power_of<N/M, M>::value; 
}; 

template<long long M> 
struct is_power_of<0, M> : public std::false_type { }; 
template<long long M> 
struct is_power_of<1, M> : public std::true_type { }; 

template<long long N, typename = typename std::enable_if<is_power_of<N, 1024>::value>::type> 
struct bytes 
{ 
    enum {value = N, next = value * 1024}; 
    template<long long M> 
    struct compile_time_get 
    { 
     enum {value = N*M}; 
    }; 
    static long long run_time_get(long long x) {return N*x;} 
}; 

typedef bytes<1> byte; 
typedef bytes<byte::next> kilo_byte; 
typedef bytes<kilo_byte::next> mega_byte; 
typedef bytes<mega_byte::next> giga_byte; 
typedef bytes<giga_byte::next> tera_byte; 
typedef bytes<tera_byte::next> peta_byte; 
typedef bytes<peta_byte::next> eksa_byte; 

int main() 
{ 
    std::cout << kilo_byte::compile_time_get<3>::value << std::endl; 
    int input = 5; 
    std::cout << mega_byte::run_time_get(input) << std::endl; 
} 

wyjściowa:

3072 
5242880 

LIVE

+36

Naprawdę mam nadzieję, że to żart. – akaltar

+3

Oczywiście, że ... nie powinieneś. –

+0

@akaltar: wyszukaj 'std :: ratio' /' std :: chrono'. –

6

Jeśli masz zamiar robić to dużo, wtedy użytkownik zdefiniowany dosłowny jest drogą do zrobienia. OTOH, dla jednorazowych (i wspieranie starszych kompilatorów i inne języki), pójdę z bezpośrednim:

size_t poolSize = 16ul*1024*1024; 
1

Wszystkie przykłady widziałem były bardziej jak

#define KB 1024 
#define MB (1024*1024) 

size_t poolSize = 16*MB; 

żadnej magii, bez pytań, po prostu działa.

+0

To są tylko liczby, więc dlaczego miałbyś używać makr zamiast "const"? –

+1

Ponieważ mogę je zapisać w nagłówku, a następnie dołączyć ten nagłówek do wielu plików bez obawy o to, jak linker poradzi sobie z pamięcią masową i innymi złożonymi elementami. Podstawienie tekstu jest łatwe do zrozumienia. – aragaer

+7

Powinny istnieć nawiasy okrągłe wokół '1024 * 1024', w przeciwnym razie dostaniesz dziwne zachowanie, jeśli i kiedy ktoś zrobi" podwójną stopę = 1,0/MB ". Zasada kciuka z '# define' jest, jeśli masz wątpliwości, * zawsze * dodaj dodatkowe nawiasy. –