Skip to content

Instantly share code, notes, and snippets.

@MaxBarraclough
Last active November 15, 2020 23:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MaxBarraclough/3063379bc8562c16745eca070b230191 to your computer and use it in GitHub Desktop.
Save MaxBarraclough/3063379bc8562c16745eca070b230191 to your computer and use it in GitHub Desktop.
Demo of the type_safe C++ library
// A small toy program to explore some of what we can do with the
// 'type_safe' library: https://github.com/foonathan/type_safe/
// We will see that we can use it to create distinct new integer types,
// capable of ordinary arithmetic, and *without* implicit conversions.
//
// We will use this to implement Ada-style strong typing, protecting
// against confusing a NumApples_type value with a NumPennies_type value.
//
// See also the official examples:
// https://github.com/foonathan/type_safe/tree/master/example
#include <cstdint> // For fixed-width integer types
#include <cinttypes> // For printf specifiers
#include <cstdio>
#include <iostream>
#include <type_safe/strong_typedef.hpp>
namespace ts = type_safe;
struct Account {
struct NumApples_type
: ts::strong_typedef<NumApples_type, uint32_t>,
ts::strong_typedef_op::integer_arithmetic<NumApples_type>,
ts::strong_typedef_op::equality_comparison<NumApples_type>,
ts::strong_typedef_op::relational_comparison<NumApples_type>
{
using strong_typedef::strong_typedef;
};
struct NumPennies_type
: ts::strong_typedef<NumPennies_type, uint32_t>,
ts::strong_typedef_op::integer_arithmetic<NumPennies_type>,
ts::strong_typedef_op::equality_comparison<NumPennies_type>,
ts::strong_typedef_op::relational_comparison<NumPennies_type>
{
using strong_typedef::strong_typedef;
};
NumApples_type num_apples;
NumPennies_type num_pennies;
inline Account(NumApples_type a, NumPennies_type p)
: num_apples(a), num_pennies(p)
{}
inline void buy_apples(
Account& counterparty_ac,
NumApples_type order_quantity,
NumPennies_type order_payment_sum_pennies
)
{
if (order_quantity <= counterparty_ac.num_apples)
{
if (order_payment_sum_pennies <= this->num_pennies)
{
this->num_apples += order_quantity; // We don't bother to check for overflow.
counterparty_ac.num_apples -= order_quantity; // Cannot underflow as we checked <=
this->num_pennies -= order_payment_sum_pennies; // Cannot underflow as we checked <=
counterparty_ac.num_pennies += order_payment_sum_pennies; // We don't bother to check for overflow.
}
else
{
puts("Cannot transfer. Buyer lacks necessary funds.");
}
}
else
{
puts("Cannot transfer. Seller has too few apples.");
}
}
static inline void explore_the_types()
{
// Let's look at what we can and can't do with these types
NumPennies_type test_pennies;
// test_pennies = 0; // Compile error. No implicit conversions, so this fails.
// test_pennies += 0; // Same again.
// NumPennies_type test_pennies2 = 0; // Compile error.
NumPennies_type test_pennies3(0); // Ok
NumApples_type test_apples(0);
// test_pennies3 += test_apples; // Compile error
// test_pennies3 = test_apples; // Compile error
}
};
int main(int argc, char *argv[])
{
Account ac1(Account::NumApples_type(10), Account::NumPennies_type(10));
Account ac2(Account::NumApples_type(100), Account::NumPennies_type(100));
ac1.buy_apples(ac2, Account::NumApples_type(5), Account::NumPennies_type(7));
// Account 1: Expect to see 15 apples and 3 pennies.
// Account 2: Expect to see 95 apples and 107 pennies.
// Whether we use the C way or the C++ way, we must explicitly cast.
// "%-10" to left align, padding to the right with spaces. UINT32_MAX is ten digits long.
printf("Account 1: Apples: %-10" PRIuLEAST32 " Pennies: %-10" PRIuLEAST32 "\n", (uint32_t)ac1.num_apples, (uint32_t)ac1.num_pennies);
printf("Account 2: Apples: %-10" PRIuLEAST32 " Pennies: %-10" PRIuLEAST32 "\n", (uint32_t)ac2.num_apples, (uint32_t)ac2.num_pennies);
// std::cout << "Account 1: Apples: " << (uint32_t)ac1.num_apples << " Pennies: " << (uint32_t)ac1.num_pennies << "\n";
// std::cout << "Account 2: Apples: " << (uint32_t)ac2.num_apples << " Pennies: " << (uint32_t)ac2.num_pennies << "\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment