我有一个接受公共API函数(在库头)struct foo &,以及该函数的内部实现调用,需要一个第三方的依赖性的功能struct bar *。
我不想将第三方依赖项引入公共头文件,因为库将以二进制形式分发,并且此依赖项是一个实现细节。
但是,我不打算附加任何附加信息foo,而是希望能够这样做reinterpret_cast<bar*>(&foo)以减少我必须执行的副本数量(这是一个非常频繁调用的函数)。
标准库是否有一个type_trait或其他一些机制来检查foo和的结构bar是否相同?我知道这将需要更多的维护保养,以确保标头也与内部依赖项的类型定义匹配,但这很好,因为它不太可能很快改变。
最终我需要类似的东西
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)
);
}
Run Code Online (Sandbox Code Playgroud)
reinterpret_cast<bar*>(&f) 由于严格别名,总是 UB。
如果没有严格别名,您可以使用 c++20's 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
Run Code Online (Sandbox Code Playgroud)