【问题标题】:What is the best way in C++ to have a compile-time constant depend on a type's size?C++ 中根据类型大小设置编译时常量的最佳方法是什么?
【发布时间】:2015-01-24 00:09:18
【问题描述】:

我在想其中之一:

#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;

另外,如何使用第二种方法引发编译时错误?

【问题讨论】:

  • 第二种方法可以使用std::static_assert
  • #if 不知道sizeof。不过,您可以使用来自limits.h 的一些宏,例如SIZE_MAX.
  • @MattMcNabb 这是一个很好的观点,我忘记了。而SIZE_MAX 仅在我关心的实际上是size_t(或其他标准类型之一)时才有效,但不一定如此。
  • 这些值是遵循某种逻辑还是任意的?看看numeric_limits
  • @NeilKirk,他们遵循一些逻辑,但逻辑对于编译时计算来说太复杂了。绝对不是numeric_limits 可以解决的问题。目前,我正在处理为 32 位和 64 位整数类型分配一个适当大的素数。

标签: c++ templates c-preprocessor compile-time-constant


【解决方案1】:

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

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

template <int S> class Foo;

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

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

【讨论】:

  • 谢谢,但这并不能回答我的主要问题。
  • @Matt:我进行了编辑以明确解决它,尽管答案的核心当然保持不变。
  • 为了记录,我只在例子中使用Foo这样的名字。
  • @Matt:他的意思不是Foo 是错误的,他的意思是Foo 的名称可以被“滥用”以在它没有的情况下显示更清晰的错误消息'存在:coliru.stacked-crooked.com/a/77b9faf649bd712ferror: incomplete type 'Environment_Where_sizeof_int_is&lt;3&gt;' used in nested name specifier
【解决方案2】:

通过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

【讨论】:

  • 谢谢,但正如我在 cmets 中指出的那样,有问题的类型不一定是标准类型之一。
  • @Matt 我实际上没有读过 cmets。我的答案也不是标准 C++,但对于那些不知道这一点的人,我认为它可以提供帮助。
【解决方案3】:

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

#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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-15
    • 1970-01-01
    • 2010-10-02
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    相关资源
    最近更新 更多