"cast to first member of standard layout" 类型双关规则是否扩展到数组?
Does the "cast to first member of standard layout" type punning rule extend to arrays?
具体来说,我将 C API 包装在一个友好的 C++ 包装器中。 C API 有这个相当标准的形状:
struct foo {...};
void get_foos(size_t* count, foo* dst);
我 喜欢 做的是,通过将类型化双关包装器 array 直接传递给C api 进行了一系列完整性检查 static_assert()
.
class fooWrapper {
foo raw_;
public:
[...]
};
std::vector<fooWrapper> get_foo_vector() {
size_t count = 0;
get_foos(&count, nullptr);
std::vector<fooWrapper> result(count);
// Is this OK?
static_assert(sizeof(foo) == sizeof(fooWrapper), "");
static_assert(std::is_standard_layout<fooWrapper>::value, "");
get_foos(&count, reinterpret_cast<foo*>(result.data()));
return result;
}
我的理解是它是有效代码,因为所有访问的内存位置都单独符合规则,但我想确认一下。
编辑: 显然,只要 reinterpret_cast<char*>(result.data() + n) == reinterpret_cast<char*>(result.data()) + n*sizeof(foo)
为真,它就会 在当今所有主要编译器下工作 。但我想知道标准是否同意。
首先,这不是双关语。您正在做的 reinterpret_cast
只是一种改写的 &result.data().foo_
方式。类型双关是通过 pointer/reference 访问一种类型的对象到另一种类型。您正在访问其他类型的子对象。
其次,这行不通。 Pointer arithmetic is based on having an array(出于指针运算的目的,单个对象充当 1 个元素的数组)。并且 vector<T>
由 fiat 定义以产生一个 T
的数组。但是 T
的数组并不等同于 T
的某个子对象的数组,即使该子对象与 T
的大小相同并且 T
是标准布局。
因此,如果get_foos
对其给定的foo
数组执行指针运算,那就是UB。哦,当然,它几乎肯定 有效 。但是语言的答案是UB。
具体来说,我将 C API 包装在一个友好的 C++ 包装器中。 C API 有这个相当标准的形状:
struct foo {...};
void get_foos(size_t* count, foo* dst);
我 喜欢 做的是,通过将类型化双关包装器 array 直接传递给C api 进行了一系列完整性检查 static_assert()
.
class fooWrapper {
foo raw_;
public:
[...]
};
std::vector<fooWrapper> get_foo_vector() {
size_t count = 0;
get_foos(&count, nullptr);
std::vector<fooWrapper> result(count);
// Is this OK?
static_assert(sizeof(foo) == sizeof(fooWrapper), "");
static_assert(std::is_standard_layout<fooWrapper>::value, "");
get_foos(&count, reinterpret_cast<foo*>(result.data()));
return result;
}
我的理解是它是有效代码,因为所有访问的内存位置都单独符合规则,但我想确认一下。
编辑: 显然,只要 reinterpret_cast<char*>(result.data() + n) == reinterpret_cast<char*>(result.data()) + n*sizeof(foo)
为真,它就会 在当今所有主要编译器下工作 。但我想知道标准是否同意。
首先,这不是双关语。您正在做的 reinterpret_cast
只是一种改写的 &result.data().foo_
方式。类型双关是通过 pointer/reference 访问一种类型的对象到另一种类型。您正在访问其他类型的子对象。
其次,这行不通。 Pointer arithmetic is based on having an array(出于指针运算的目的,单个对象充当 1 个元素的数组)。并且 vector<T>
由 fiat 定义以产生一个 T
的数组。但是 T
的数组并不等同于 T
的某个子对象的数组,即使该子对象与 T
的大小相同并且 T
是标准布局。
因此,如果get_foos
对其给定的foo
数组执行指针运算,那就是UB。哦,当然,它几乎肯定 有效 。但是语言的答案是UB。