Skip to content

Commit e32dbdd

Browse files
committed
add padding section
1 parent 4756013 commit e32dbdd

File tree

4 files changed

+81
-1
lines changed

4 files changed

+81
-1
lines changed

.github/DockerClang

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
FROM ubuntu:latest
22

3+
# git clone -b p2996 https://github.com/Yaraslaut/clang-p2996.git && \
34
WORKDIR /
45
RUN apt-get update
56
RUN apt-get install -y cmake python3 ninja-build git lsb-release software-properties-common wget binutils gcc g++
67
#RUN bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
78
RUN bash -c "\
89
set -ex && \
9-
git clone -b p2996 https://github.com/Yaraslaut/clang-p2996.git && \
10+
git clone -b p2996 https://github.com/bloomberg/clang-p2996.git && \
1011
cmake -S /clang-p2996/llvm \
1112
-B build \
1213
-G Ninja \

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,41 @@ void EnumToString() {
5555
}
5656
```
5757

58+
## Padding check at compile time
59+
60+
Calculate padding at compile time and enforce zero padding via concepts
61+
62+
``` c++
63+
64+
65+
struct struct_with_padding {
66+
char a;
67+
double c;
68+
};
69+
70+
struct struct_no_padding {
71+
double c;
72+
char a;
73+
};
74+
75+
template <form::no_padding T> void foo(T t) {
76+
std::println("Without padding");
77+
}
78+
79+
template <typename T> void foo(T t) {
80+
std::println("With padding: {}", form::get_padding<T>());
81+
}
82+
83+
84+
void PaddingCheck() {
85+
foo(struct_with_padding{}); // With padding: 7
86+
foo(struct_no_padding{}); // Without padding
87+
static_assert(form::no_padding<struct_no_padding>);
88+
}
89+
90+
91+
```
92+
5893
`
5994
6095
## Variant type to string

include/form/form.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,27 @@ template <typename T> constexpr void print_members() {
102102
};
103103
}
104104

105+
template <typename S> consteval std::size_t get_padding() {
106+
107+
std::size_t padding{0};
108+
std::size_t pointer{offset_of(nonstatic_data_members_of(^S)[0])};
109+
110+
[: util::expand(nonstatic_data_members_of(^S)):] >> [&, i = 0]<auto e>() {
111+
if (pointer == offset_of(e))
112+
pointer += size_of(e);
113+
else {
114+
padding += offset_of(e) - pointer;
115+
pointer = offset_of(e) + size_of(e);
116+
}
117+
};
118+
return padding;
119+
}
120+
121+
template <typename T>
122+
concept no_padding =
123+
std::same_as<std::integral_constant<std::size_t, get_padding<T>()>,
124+
std::integral_constant<std::size_t, 0>>;
125+
105126
} // namespace form
106127

107128
template <> struct std::formatter<std::basic_string_view<char8_t>> {

src/test.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,22 @@ enum class Decorator : uint8_t {
334334
Encircle,
335335
};
336336

337+
struct struct_with_padding {
338+
char a;
339+
double c;
340+
};
341+
342+
struct struct_no_padding {
343+
double c;
344+
char a;
345+
};
346+
347+
template <form::no_padding T> void foo(T t) { std::println("Without padding"); }
348+
349+
template <typename T> void foo(T t) {
350+
std::println("With padding: {}", form::get_padding<T>());
351+
}
352+
337353
namespace form::examples {
338354
bool VariantCreate() {
339355
list_variant v{list::CancelSelection{}};
@@ -366,6 +382,13 @@ bool EnumToStringWithTransform() {
366382
return res;
367383
}
368384

385+
void PaddingCheck() {
386+
387+
foo(struct_with_padding{});
388+
foo(struct_no_padding{});
389+
static_assert(form::no_padding<struct_no_padding>);
390+
}
391+
369392
} // namespace form::examples
370393

371394
void ExampleConfig() {

0 commit comments

Comments
 (0)