Last active
November 15, 2020 19:59
-
-
Save MaxBarraclough/088047135c1a1d7767f5ec82199c7815 to your computer and use it in GitHub Desktop.
BOOST_STRONG_TYPEDEF Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A small toy program (in fact it does nothing at all) | |
// to explore what we can do with BOOST_STRONG_TYPEDEF. | |
// We will see that it creates a distinct new type, with permissive | |
// implicit conversions regarding the original type. | |
// | |
// BOOST_STRONG_TYPEDEF has its uses, but we will see that we can't use | |
// BOOST_STRONG_TYPEDEF to implement Ada-style strong typing, such as to protect | |
// against confusing a NumApples_type value with a NumPennies_type value. | |
#include <cstdint> | |
#include <type_traits> | |
#include <array> | |
#include <vector> | |
#include <boost/serialization/strong_typedef.hpp> | |
struct Account { | |
BOOST_STRONG_TYPEDEF(uint32_t, NumApples_type) | |
BOOST_STRONG_TYPEDEF(uint32_t, NumPennies_type) // No need for floating-point | |
typedef uint32_t Typedef_uint32t; // Example ordinary typedef | |
// Let's confirm that ordinary typedefs work the way they always do, | |
// introducing an alias rather than a new type. | |
static_assert( std::is_same<Typedef_uint32t, uint32_t >::value ); | |
// Let's confirm that BOOST_STRONG_TYPEDEF has given us new types, | |
// unlike an ordinary typedef. | |
static_assert( !std::is_same<NumApples_type, uint32_t >::value ); | |
static_assert( !std::is_same<NumPennies_type, uint32_t >::value ); | |
static_assert( !std::is_same<NumApples_type, NumPennies_type>::value ); | |
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 | |
) | |
{ | |
if (counterparty_ac.num_apples >= order_quantity) | |
{ | |
if (this->num_pennies >= order_payment_sum) | |
{ | |
this->num_apples += order_quantity; // We don't bother to check for overflow. | |
counterparty_ac.num_apples -= order_quantity; // Cannot underflow, as we checked for 0. | |
this->num_pennies -= order_payment_sum; // Cannot underflow as we checked for 0. | |
counterparty_ac.num_pennies += order_payment_sum; // 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."); | |
} | |
} | |
// Let's look at what we can and can't do with these types | |
static inline void explore_the_types() | |
{ | |
NumPennies_type test_pennies; | |
NumApples_type test_apples(0); | |
// NumPennies_type test_pennies2 = 0; // Compile error. | |
NumPennies_type test_pennies2(0); // Ok | |
// These compile fine, as the type we get from BOOST_STRONG_TYPEDEF | |
// includes implicit conversion back to the 'original' type. | |
test_pennies = 0; | |
test_pennies += 42; | |
uint32_t test_pennies_uint32 = test_pennies; | |
// These two statements compile fine too. | |
// If we want to use type safety to prevent 'crossing the beams' in this way, | |
// BOOST_STRONG_TYPEDEF isn't the right tool. | |
// Instead we might consider the 'type_safe' library, see | |
// https://github.com/foonathan/type_safe/ | |
// See also a whirlwind tour of it at | |
// https://gist.github.com/MaxBarraclough/3063379bc8562c16745eca070b230191 | |
test_pennies = test_apples; | |
test_pennies += test_apples; | |
// Let's look at some collections from the C++ standard library | |
std::vector<NumPennies_type> pennies_vec; | |
std::vector<NumApples_type> apples_vec; | |
// pennies_vec = apples_vec; | |
// Compile error, due to invariance. See: | |
// * https://softwareengineering.stackexchange.com/a/399279/ | |
// * https://cpptruths.blogspot.com/2015/11/covariance-and-contravariance-in-c.html | |
std::array<NumPennies_type,2> pennies_stdarr; | |
std::array<NumApples_type ,2> apples_stdarr; | |
// pennies_stdarr = apples_stdarr; // Compile error, same reason as above. | |
} | |
}; | |
int main(int argc, char *argv[]) | |
{ | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment