可以使用“offsetof”来获取通过“decltype”获得的结构类型吗?

4

offsetof能否与通过decltype获取的类型一起使用?这两种情况在C++11中是否有效?

struct S {
  int i;
  int j { offsetof(decltype(*this), i) };  // case 1
  S() : i(offsetof(decltype(*this), j)) {}; // case 2
} inst1;

int main() {
  struct {
    int i;
    int j { offsetof(decltype(*this), i) }; // case 3
  } inst2;
  return 0;
}

在苹果LLVM版本6.0(clang-600.0.57)(基于LLVM 3.5svn)下,它们都无法编译,并伴有以下错误:

error: offsetof requires struct, union, or class type, 
'decltype(*this)' (aka '<anonymous struct at ../qxjs3uu/main.cpp:4:4> &') invalid

看起来它也会导致MSVC 19.00.23106.0(x86)内部错误而崩溃:

Compiled with  /EHsc /nologo /W4 /c
main.cpp
main.cpp(3): error C2062: type 'S &' unexpected
[...]
main.cpp(4): fatal error C1903: unable to recover from previous error(s); stopping compilation
Internal Compiler Error in c:\tools_root\cl\bin\i386\cl.exe.  You will be prompted to send an error report to Microsoft later.

我有没有想到测试用例编写者没有想到的东西?
2个回答

6
指针解除引用的结果是一个lvalue(并且本身也是一个表达式),因此decltype(*this)为您提供类型S&
§ 7.1.6.2 [dcl.type.simple]/p4:
“ decltype(e)”表示的类型定义如下:
- [...] - 否则,如果“ e”是左值,则“ decltype(e)”为“ T&”,其中“ T”是“ e”的类型;
要将其用作offsetof的参数,您需要从decltype()限定符获得的类型中删除引用:
offsetof(std::remove_reference<decltype(*this)>::type, i)

DEMO


太棒了,这正是我所需要的。我没有意识到 offsetof 是如此挑剔,一个简单的引用就能让它失去平衡 :) - Kuba hasn't forgotten Monica
@KubaOber 这不是 offsetof 的错;更多的是因为引用很奇怪。 - The Paramagnetic Croissant
2
仔细阅读这些错误消息可以发现它们都隐藏着 & 符号。但是,为了看到它,必须非常仔细地阅读以下错误信息: error: offsetof requires struct, union, or class type, 'decltype(*this)' (aka '<anonymous struct at ../qxjs3uu/main.cpp:4:4> &') invalid - Toby Speight
1
@TobySpeight,这还需要理解struct [...] type字面上意思是一个结构体而不是指向结构体的引用。这正是我之前不知道的。我已经在这个答案中将其应用于一些(不一定好的)用途。 - Kuba hasn't forgotten Monica

2

它们可以一起使用。以这个例子为例:

#include <iostream>
#include <string>
#include <stddef.h>

int main()
{
  struct S {
   int a;
   int b;
  };
  S instance;
  std::cout << "offset: " << offsetof(decltype(instance), b) << "\n";
  return 0;
}

哪个会打印偏移量:4

我认为您的问题源于使用decltype(* this),根据C++11标准的5.1.1,我不确定它是否会按照您的期望执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接