C++ 中使编译时常量取决于类型大小的最佳方法是什么?

What is the best way in C++ to have a compile-time constant depend on a type's size?

我在想其中之一:

#if sizeof(size_t) == 8
const size_t foo = 12345;
#elif sizeof(size_t) == 4
const size_t foo = 123;
#else
#error "Unsupported size_t size"
#endif

template <int S> class Foo { static const size_t foo = 0; };
template <> class Foo<8> { static const size_t foo = 12345; };
template <> class Foo<4> { static const size_t foo = 123; };
const size_t foo = Foo<sizeof(size_t)>::foo;

此外,如何使用第二种方法抛出编译时错误?

使用 class 模板的解决方案是一种很好的惯用方法(第一种选择也行不通,因此这两个候选者之间没有竞争)。

要导致编译时错误,请不要为所有尺寸定义模板:

template <int S> class Foo;

然后编译器会抱怨没有为 sizeof(size_t) 的违规值定义模板。

将名称从 Foo 更改为 Environment_Where_sizeof_int_is 之类的名称也会有所帮助——您在实践中会遇到更多可立即理解的编译器错误。

通过 g++ 您还可以使用以下预定义的宏:

__SIZEOF_SIZE_T__
__SIZEOF_INT__
__SIZEOF_LONG__

(其他类型依此类推,完整列表见documentation)。

例如:

#if __SIZEOF_SIZE_T__ == 8
const size_t foo = 12345;
#elif __SIZEOF_SIZE_T__ == 4
const size_t foo = 123;
#else
#error "Unsupported size_t size"
#endif

使用已定义结构的第一个和第二个成员的类型并获取第二个成员的偏移量以获得第一个成员的大小(这假设第一个和第二个成员之间没有填充,保证第一个成员与结构具有相同的地址)。

#define ofs(s,m)   (size_t)&(((s *)0)->m)

typedef struct S_{
size_t a;       /* type to get the size of */
size_t b;       /* make this same type as above */
}S;

int main()
{
size_t c;
    c = ofs(S,b);   /* get size of S.a */
    return(0);
}