如何写一个像"size_t s = 16 MByte"的文字常量?

Per*_*est 40 c++

今天在我们的代码库中发现了以下行并且喜欢它的优雅来编写内存大小.想知道这是如何编译的几分钟.

size_t poolSize = 16 MByte;
Run Code Online (Sandbox Code Playgroud)

一个解决方案是我自己的答案.还有其他方法吗?

Che*_*Alf 85

在现代C++中,您应该定义一个文字符号,例如

auto operator""_MB( unsigned long long const x )
    -> long
{ return 1024L*1024L*x; }
Run Code Online (Sandbox Code Playgroud)

然后写

long const poolSize = 16_MB;
Run Code Online (Sandbox Code Playgroud)

不要使用宏,它们是Evil™.在很多方面.


免责声明:编译器未触及的代码.

  • MiB会更准确 (24认同)
  • 除非我们继续坚持使用它们,否则它们不会流行起来. (15认同)
  • 你为什么采用`unsigned long long`,但是返回一个超过_million_倍的值只是一个'long`?肯定至少会返回`unsigned long long`? (12认同)
  • @TemplateRex:我曾经认为大约15年多以前.但那些单位名称从未流行过.与其他许多事情一样,我们陷入了冻结的历史. (8认同)
  • 将*M*定义为与百万不同的东西远比任何宏都要邪恶. (4认同)
  • 对于更多二进制/十进制乐趣,请考虑电信E1"2 Mbps"租用线路.这些实际上以2048000 bps运行.那不是2*10 ^ 6,也不是2 ^ 21,而是2 ^ 11*10 ^ 3. (2认同)
  • @ Cheersandhth.-Alf:我知道,但返回类型取决于你. (2认同)
  • @ Cheersandhth.-Alf(Re:MiB)Git正确使用了KiB等. (2认同)

xin*_*aiz 11

当然你应该使用模板元编程来解决这个问题:

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

3072
5242880
Run Code Online (Sandbox Code Playgroud)

生活

  • 我真的希望这是一个笑话. (37认同)

Mar*_*ica 6

如果你要做很多事情,那么用户定义的文字是要走的路.OTOH,对于一次性(并支持较旧的编译器和其他语言),我会直接使用:

size_t poolSize = 16ul*1024*1024;
Run Code Online (Sandbox Code Playgroud)


Per*_*est 5

这是一个简单而巧妙地使用好的旧宏.

#define KByte *1024
#define MByte *1024*1024
#define GByte *1024*1024*1024
Run Code Online (Sandbox Code Playgroud)

所以size_t poolSize = 16 MByte;被翻译成

size_t poolSize = 16 *1024*1024;
Run Code Online (Sandbox Code Playgroud)

  • 这是一个简单而可怕的宏滥用.永远不要这样做. (47认同)
  • 10 - 15年前使用类似"16*MBYTE"的东西会更好,如果不需要在常量表达式中使用,最好将MBYTE定义为静态常量.宏的一个问题是`var/1 MByte`不会像看起来那样将`var`除以兆字节,而是将它乘以兆字节. (21认同)
  • 如果你必须继续使用宏,至少应该_really_像`#define KByte(x)((x)*1024)`,`#define MByte(x)((x)*1024*1024 )`和`#define GByte(x)((x)*1024*1024*1024)`,所以它不太可能破坏某些东西.当然,这意味着进行一些重构,但是如果你滥用当前的宏,它会比任何可能发生的疯狂更好. (16认同)
  • 100ull MByte/16 MByte给出6871947673600,没有ull它只会溢出.谨慎使用. (3认同)
  • 是的,这真的没什么"聪明"的! (2认同)