检查两种类型是否可以别名

Check if two types can be aliased

我有一个 public API 函数(在库 header 中)接受 struct foo &,并且该函数的内部实现调用 third-party需要 struct bar *.

的依赖函数

我不想将第三方依赖项引入 public header,因为库将以二进制形式分发,并且此依赖项是一个实现细节。

但是,我不打算将任何附加信息附加到 foo,而是希望能够执行 reinterpret_cast<bar*>(&foo) 以减少我必须执行的副本数量(这是一个经常被调用的函数)。

标准库是否有 type_trait 或其他机制来检查 foobar 的结构是否相同?我知道这将需要我进行更多维护以确保 header 也与内部依赖项的类型定义相匹配,但这很好,因为它不太可能很快改变。

最终我需要类似

的东西
struct foo {
    int a;
    const char *b;
};

struct bar {
    int c;
    const char *d;
};

static_assert(
    std::is_aliasable_to<foo, bar>::value, //        <-- Is this possible?
    "foo must be structurally equivalent to bar"
);

void public_api_function(foo &f) {
    private_third_party_function(
        reinterpret_cast<bar*>(&f)
    );
}

reinterpret_cast<bar*>(&f) 总是 UB 因为 strict-aliasing.

如果没有 strict-aliasing,您可以使用 c++20 的 std::is_layout_compatible,但没有任何编译器支持。

您可以使用这样的技巧:

template<typename T, typename U>
constexpr bool is_same_member_type(T foo::*, U bar::*) {
    return std::is_same_v<T, U>;
}

#define HAS_SAME_MEMBER(foo_name, bar_name) (offsetof(foo, foo_name) == offsetof(bar, bar_name) && is_same_member_type(&foo:: foo_name, &bar:: bar_name))

// add more HAS_SAME_MEMBER calls if new members are added
static_assert(
    sizeof(foo) == sizeof(bar) &&
    std::is_standard_layout_v<foo> && std::is_standard_layout_v<bar> &&
    HAS_SAME_MEMBER(a, c) &&
    HAS_SAME_MEMBER(b, d),
    "foo must be structurally equivalent to bar"
);

#undef HAS_SAME_MEMBER