自学内容网 自学内容网

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);

注意,e0e1成员需要分开写,否则这两个成员依然是相同类型.再回到前面的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)!