公共基类打破元组的空基类优化 [英] Common base class breaks empty base class optimization for tuples

查看:202
本文介绍了公共基类打破元组的空基类优化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

gcc 4.7.1对元组执行空基类优化,我认为这是一个非常有用的功能。但是,这似乎有一个意想不到的限制:

gcc 4.7.1 does empty base class optimization for tuples, which I consider a really useful feature. However, there appears to be an unexpected limit to this:

#include <tuple>
#include <cstdint>
#include <type_traits>
class A { };
class B : public A { std::uint32_t v_; };
class C : public A { };
static_assert(sizeof(B) == 4,                "A has 32 bits.");
static_assert(std::is_empty<C>::value,       "B is empty.");
static_assert(sizeof(std::tuple<B, C>) == 4, "C should be 32 bits.");

在这种情况下,最后一个断言失败,因为元组实际上大于4个字节。有没有办法避免这种情况,而不打破类层次结构?

In this case, the last assertion fails, as the tuple is in fact larger than 4 bytes. Is there a way to avoid this, without breaking the class hierarchy? Or do I have to implement my own pair implementation which optimizes for this case in some other way?

推荐答案

这是一个空的原因对象必须占用一些空间是两个不同的对象必须具有不同的地址。例外的是,派生类型的基本子对象可以具有与派生完整对象相同的地址(如果派生类型的第一个非静态成员与基本 [*]的类型不同, 。空基本优化使用它来删除任意添加到空基的额外空间,以确保任何完整对象的 sizeof x!= 0

The reason that an empty object must take some space is that two different objects must have different addresses. The exception to that is that the base subobject of a derived type can have the same address as the derived complete object (if the first non-static member of the derived type is not of the same type as the base [*]. The empty base optimization uses that to remove the additional space that is added to an empty base arbitrarily to ensure that sizeof x!=0 for any complete object.

在这种情况下,元组保存两个 A 子对象,基础 C 另一个是 B 的基础,但它们是不同所以它们必须有不同的地址,这两个对象都不是另一个对象的基本子对象,所以它们不能有相同的地址,你甚至不需要使用 std :: tuple 看到这种效果,只是创建另一种类型:

In your case, the tuple is holding two A subobjects, one is the base of C the other is the base of B, but they are different and as such they must have different addresses. None of those two objects is the base subobject of the other, so they cannot have the same address. You don't even need to use std::tuple to see this effect, just create another type:

struct D : B, C {};

D 的大小将严格大于 B C 。要检查事实上有两个 A 子对象,您可以尝试将upcast指向 A 的指针,编译器

The size of D will be strictly greater than the size of both B and C. To check that there are in fact two A subobjects, you can try to upcast to a pointer to A and the compiler will gladly spit some ambiguity error in your direction.

[*] 标准也明确禁止这种情况,原因也一样:

[*] The standard explicitly forbids this case also, for the same reason:

struct A {};
struct B : A { A a; };

在这种情况下,在 B ,有两个 A 对象,它们必须有不同的地址。

Again, in this case in each complete object of type B, there are two A objects, and they must have different addresses.

这篇关于公共基类打破元组的空基类优化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆