A Few Good Types - Neil MacIntosh - CppCon 2015
A Few Good Types - Neil MacIntosh - CppCon 2015
Neil MacIntosh
[email protected]
Before After
void f(_In_reads_(num) Thing* things, unsigned count) { void f(array_view<const Thing> things) {
unsigned totalSize = 0; unsigned totalSize = 0;
for (unsigned i = 0; i <= count; ++i) for (auto& thing : things)
totalSize += things[i].GetSize(); totalSize += thing.GetSize();
// SA can catch this error today
} }
• Type safety
• Ensure that unsafe type conversions are prevented
• Efficiency
• Zero-overhead when compared to equivalent hand-written checks.
• Low-overhead compared to unsafe code it replaces
• Abstraction
• Separate concerns: data access (view) from storage (container)
// write foo
Foo* foo = (Foo*)packet;
foo->someEntry = ...; // write the fields of foo
Wait, WHAT?
// write bar
packet += sizeof(Foo);
Bar* bar = (Bar*)packet;
bar->someField = ...; // write the fields of bar
// write a fuzzbuzz
packet += sizeof(Bar);
FuzzBuzz* fuzzbuzz = (FuzzBuzz*)packet;
fuzzbuzz->anotherField = ...; // write the fields of fuzzbuzz
}
CppCon 2015 A Few Good Types 7
int read(array_view<byte> packet, /*other stuff*/) {
// write foo
auto foo = p.as_array_view<Foo, 1>();
foo[0].someEntry = ...; // write the fields of foo
// write bar
p = p.sub(sizeof(Foo));
auto bar = p.as_array_view<Bar, 1>();
bar[0].someField = ...; // write the fields of bar
// write a fuzzbuzz
p = p.sub(sizeof(Bar)); Safe: will fail-fast.
auto fuzzbuzz = p.as_array_view<FuzzBuzz,1>();
fuzzbuzz[0].anotherField = ...; // write the fields of fuzzbuzz
}
CppCon 2015 A Few Good Types 8
Safety Features
• Only allow safe conversions
int arr[] = { 1, 2, 3, 4 };
array_view<int, 4> av4 = arr; // safe, fixed size view of 4
while (cchText)
{
if (*szText == '&')
Write(“&”, sizeof(“&”)); Whoops!
else
Write(szText, 1);
cchText--;
szText++;
}
}
auto it = text.begin();
while (it != text.end())
{
if (*it == '&') // bounds-checked
Write(ensure_z(“&”)); // safe and explicit
else
Write({*it, 1});
++it; // bounds-checked
}
}
Sound familiar?
• All accesses are bounds-checked. Always.
• Violations result in fail-fast.
• Convenient aliases for common cases: “w”ide chars and “c”onst views
• string_view
• cstring_view
• wstring_view
• cwstring_view
void f(my_array a) {
// a is effectively a pointer, and the compiler
// knows that from here, the value of that pointer cannot change
void f(array_view<int,9> p) {
// p contains a single int*. The compiler knows that from here on
// the value of that int* cannot change.
• Resources:
• https://github.com/Microsoft/GSL (reference implementation)
• http://isocpp.org/ (for links to the array_view and string_view proposals)