update 在实际应用中,由于有多个基类,所以初始化时简单的{3}会让编译器不清楚它是初始化什么的,给出警告
warning: suggest braces around initialization of subobject [-Wmissing-braces]
所以目前只是glimpse,看起来非常美好,尝试着用起来还是有不少问题的
Safe and Sane C++ Types - Peter Sommerlad [ACCU 2019]
用POD包裹一切可能误用的类型,例如foo(int, int, int),虽然有性能代价,但是从维护性上来讲大约绝大对数情况下是值得的
EBO和CRTP很大程度上简化类似类型的使用 最后一个断言似乎是错误的,c.val的应该是2
#include <catch2/catch.hpp> template <typename T, typename TAG> struct strong { using value_type = T; T val{}; }; template <typename T> struct Eq { friend constexpr bool operator==(const T &l, const T &r) noexcept { return l.val == r.val; } friend constexpr bool operator!=(const T &l, const T &r) noexcept { return !(l == r); } }; template <typename T> struct Inc { friend constexpr auto operator++(T &rv) noexcept { ++rv.val; return rv; } friend constexpr auto operator++(T &rv, int) noexcept { auto org{rv}; ++rv; return org; } }; template <typename T> struct Out { friend std::ostream &operator<<(std::ostream &os, const T &r) { return os << r.val; } }; template <typename T, template <typename ... > class ... BS> struct ops : BS<T> ... {}; struct SomeType : strong<unsigned, SomeType>, ops<SomeType, Eq, Inc, Out>{}; [[nodiscard]] auto SomeTypeCreator(unsigned v=0) -> SomeType { return {{v}, {}}; } static_assert(sizeof(SomeType) == sizeof(SomeType::value_type)); TEST_CASE("Peter's Simple Strong Typing") { auto t{SomeTypeCreator()}; const auto ct{SomeTypeCreator(1)}; REQUIRE(SomeTypeCreator() == t); REQUIRE(ct == ++t); REQUIRE(ct == t++); REQUIRE(2 == t.val); }