#pragma once /////////////////////////////////////////////////////////////////////// // NamedType.h - Defines Strong Types // // // // Jim Fawcett, CSE687 - Object Oriented Design, Spring 2018 // /////////////////////////////////////////////////////////////////////// // // Acknowledgement: // -Almost all of the ideas used in this solution were discussed clearly by // Jonathan Boccara here : // https://www.fluentcpp.com/2016/12/08/strong-types-for-strong-interfaces/ // // - The code given here has adaptions of his code samples. #include #include template class NamedType { public: explicit NamedType(T const& value) : value_(value) {} T& get() { return value_; } T const& get() const { return value_; } explicit operator T&() { return value_; } private: T value_; }; template std::ostream& operator<<(std::ostream& out, NamedType& arg) { out << arg.get(); return out; } template class crtpType> struct crtp { T& underlying() { return static_cast(*this); } T const& underlying() const { return static_cast(*this); } }; template struct Addable : crtp { T operator+(T const& other) { return T(this->underlying().get() + other.get()); } T operator-(T const& other) { return T(this->underlying().get() - other.get()); } }; template class AddableNamedType : public Addable> { public: explicit AddableNamedType(T const& value) : value_(value) {} T& get() { return value_; } T const& get() const { return value_; } explicit operator T&() { return value_; } private: T value_; }; template std::ostream& operator<<(std::ostream& out, AddableNamedType& arg) { out << arg.get(); return out; } using Meter = AddableNamedType; using Yard = AddableNamedType; //template //class AddableNamedType : public NamedType, Addable> {};