C++在预处理器 #if 中进行 sizeof() 比较时抛出编译错误
我有这个,它不会从 Visual Studio 编译错误“致命错误 C1017:无效的整数常量表达式”。我该怎么做?
template <class B>
A *Create()
{
#if sizeof(B) > sizeof(A)
#error sizeof(B) > sizeof(A)!
#endif
...
}
I have this which does not compile with the error "fatal error C1017: invalid integer constant expression" from visual studio. How would I do this?
template <class B>
A *Create()
{
#if sizeof(B) > sizeof(A)
#error sizeof(B) > sizeof(A)!
#endif
...
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
预处理器不理解 sizeof() (或数据类型、标识符、模板或类定义,并且它需要理解所有这些内容才能实现 sizeof)。
您正在寻找的是静态断言(由编译器强制执行,它确实理解所有这些事情)。我为此使用 Boost.StaticAssert :
The preprocessor does not understand sizeof() (or data types, or identifiers, or templates, or class definitions, and it would need to understand all of those things to implement sizeof).
What you're looking for is a static assertion (enforced by the compiler, which does understand all of these things). I use Boost.StaticAssert for this:
预处理器表达式在编译器开始编译之前进行评估。 sizeof() 仅由编译器计算。
Preprocessor expressions are evaluated before the compiler starts compilation. sizeof() is only evaluated by the compiler.
你不能用预处理器来做到这一点。预处理器指令不能与诸如
sizeof
这样的语言级元素一起操作。此外,即使它们可以,它仍然无法工作,因为预处理器指令很早就从代码中消除了,所以不能期望它们作为稍后实例化的模板代码的一部分来工作(这就是您似乎试图做的)达到)。正确的方法是使用某种形式的静态断言。
静态断言有很多实现。进行搜索并选择一个最适合您的。
You can't do this with preprocessor. Preprocessor directives cannot operate with such language-level elements as
sizeof
. Moreover, even if they could, it still wouldn't work, since preprocessor directives are eliminated from the code very early, they can't be expected to work as part of template code instantiated later (which is what you seem to be trying to achieve).The proper way to go about it is to use some form of static assertion
There are quite a few implementations of static assertions out there. Do a search and choose one that looks best to you.
sizeof() 不能在预处理器指令中使用。
sizeof() cannot be used in a preprocessor directive.
预处理器在编译器之前运行(至少在逻辑上是这样),并且不了解用户定义的类型(并且不一定对内在类型了解很多 - 预处理器的 int 大小可能与编译器目标不同。
无论如何,做你想做的,您应该使用
STATIC_ASSERT()
。请参阅以下答案:使用
STATIC_ASSERT()
您将能够执行此操作:The preprocessor runs before the compiler (at least logically it does) and has no knowledge of user defined types (and not necessarily much knowledge about intrinsic types - the preprocessor's int size could be different than the compiler targets.
Anyway, to do what you want, you should use a
STATIC_ASSERT()
. See the following answer:With a
STATIC_ASSERT()
you'll be able to do this:这无法通过预处理器来完成。预处理器在编译器之前执行,因此在计算
#if
时尚未计算 NodeB 和 Node 的大小。您可以使用模板编程技术来完成类似的事情。关于该主题的一本优秀书籍是 Andrei Alexandrescu 所著的《现代 C++ 设计:通用编程和设计模式应用》。
这是一个网页示例,它创建了一个模板 IF陈述。
在该示例中,您可以使用:::RET i;
<代码>如果< sizeof(NodeB)
声明一个
int
类型或non_existing_type
类型的变量。假设不存在的类型名副其实,如果模板 IF 条件评估为 true,则会导致编译器错误。您可以将i
重命名为具有描述性的名称。使用这个将是“滚动你自己的”静态断言,其中许多已经可用。我建议您在自己尝试构建一个之后使用其中之一。
This cannot be accomplished with pre-processor . The pre-processor executes in a pass prior to the compiler -- therefore the sizes of NodeB and Node have not yet been computed at the time
#if
is evaluated.You could accomplish something similar using template-programming techniques. An excellent book on the subject is Modern C++ Design: Generic Programming and Design Patterns Applied, by Andrei Alexandrescu.
Here is an example from a web page which creates a template IF statement.
From that example, you could use:
IF< sizeof(NodeB)<sizeof(Node), non_existing_type, int>::RET i;
which either declares a variable of type
int
or of typenon_existing_type
. Assuming the non-existing type lives up to its name should the template IF condition evaluate as true, a compiler error will result. You can renamei
something descriptive.Using this would be "rolling your own" static assert, of which many are already available. I suggest you use one of those after playing around with building one yourself.
如果您对适用于 C 和 C++ 的编译时断言感兴趣,这里是我开发的一个:
它的工作原理是,当表达式为 false 时,数组的大小为负数(这是非法的)。通过进一步将其包装在结构定义中,这不会在运行时创建任何内容。
If you are interested in a compile time assert that will work for both C and C++, here is one I developed:
The to how this works is that the size of the array is negative (which is illegal) when the expression is false. By further wrapping that in a structure definition, this does not create anything at runtime.
这已经被解释过,但请允许我详细说明为什么预处理器无法计算结构的大小。除了这对于简单的预处理器来说要求过高之外,还有一些编译器标志会影响结构的布局方式。
<代码>结构X {
短一个;
长b;
};
该结构可能是 6 字节或 8 字节长,具体取决于编译器是否被告知出于性能原因对“b”字段进行 32 位对齐。预处理器不可能获得该信息。
This has already been explained, but allow me to elaborate on why the preprocessor can not compute the size of a structure. Aside from the fact that this is too much to ask of a simple preprocessor, there are also compiler flags that affect the way the structure is laid out.
struct X {
short a;
long b;
};
this structure might be 6 bytes or 8 bytes long, depending on whether the compiler was told to 32-bit align the "b" field, for performance reasons. There's no way the preprocessor could have that information.
使用 MSVC,这段代码可以为我编译:
但是这(应该以相同的方式工作)却不能:
#if ( sizeof(void*) == 4 )
...
Using MSVC, this code compiles for me:
however this (which should work identically) does not:
#if ( sizeof(void*) == 4 )
...
我看到很多人说 sizeof 不能在预处理器指令中使用,
然而,这并不是全部,因为我经常使用以下宏:
例如:
yields:
但是
我也无法在gcc 4.2下的#if语句中编译sizeof()。 1.
例如,这不会编译:
任何见解将不胜感激。
i see many people say that sizeof cannot be used in a pre-processor directive,
however that can't be the whole story because i regularly use the following macro:
for example:
yields:
however
i, too, cannot get sizeof() to compile in a #if statement under gcc 4.2.1.
eg, this doesn't compile:
any insight would be appreciated.