2411C++,无唯一地址
原文
C++20
新增的[[no_unique_address]]
属性一般可替代传统的EBO
,但是,除了代替EBO
,还可用该属性
来实现条件成员
,代码如下:
#include <cstdint>
#include <type_traits>
struct empty { };
template <bool C>
struct apple {
[[no_unique_address]] std::conditional_t<C, int, empty> sn;
std::uint64_t weight;
};
static_assert(sizeof(apple<true>) == 16);
static_assert(sizeof(apple<false>) == 8);
当然,sn
成员并没有消失,可访问任意类型
,只是为空的
类型时,空间占用
变为了0
,虽然不很完美,但只从内存布局
上来看,已实现了条件成员
这一功能.
则,事情结束了吗?请考虑如下代码
:
struct one_empty {
[[no_unique_address]] empty e;
};
static_assert(sizeof(one_empty) == 1);
struct all_empty {
[[no_unique_address]] empty e0, e1;
};
static_assert(sizeof(all_empty) == 2);
all_empty
大小为2
,在[[no_unique_address]]
的p0480r2
提案中的第一个常见问题
就有解答,相同类型的子对象
的地址不能相同,所以这里e0
成员的偏移
为0
,e1
的偏移
为1
,于是,可完善一下以上代码
,利用λ
类型的唯一性
来解决,代码如下:
template <typename = decltype([]() {})>
struct unique_empty { };
struct all_unique_empty {
[[no_unique_address]] unique_empty<> e0;
[[no_unique_address]] unique_empty<> e1;
};
static_assert(sizeof(all_unique_empty) == 1);
注意,e0
和e1
成员需要分开写
,否则这两个成员
依然是相同类型
.再回到前面的all_empty
的定义,如果有相同类型
的空成员
,则sizeof
的结果就不是1
,于是,可利用这一特性
去判断是否有0
重复类型,代码如下:
template <typename T>
struct empty_wrap { };
template <typename... Ts>
struct empty_box;
template <>
struct empty_box<> { };
template <typename T, typename... Ts>
struct empty_box<T, Ts...> : public empty_box<Ts...> {
[[no_unique_address]] empty_wrap<T> e;
};
template <class... Ts>
constexpr bool is_type_pack_set_v = (sizeof(empty_box<Ts...>) == 1);
template <class... Ts>
constexpr bool is_type_pack_multiset_v = !is_type_pack_set_v<Ts...>;
该代码是通过递归继承
实现的,如前,相同类型
的子对象
地址不能相同
,所以可用继承实现这一问题
,无重复元素
为set
,有重复元素
为多集
,测试代码如下:
static_assert(is_type_pack_set_v<>);
static_assert(is_type_pack_set_v<char>);
static_assert(is_type_pack_set_v<char, unsigned char>);
static_assert(is_type_pack_multiset_v<char, unsigned char, unsigned char>);
static_assert(is_type_pack_multiset_v<char, unsigned char, char>);
原文地址:https://blog.csdn.net/fqbqrr/article/details/144103191
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!