File indexing completed on 2025-10-12 04:59:54

0001 // bjgb_rank.h                                                        -*-C++-*-
0002 #ifndef INCLUDED_BJGB_RANK
0003 #define INCLUDED_BJGB_RANK
0004 
0005 //@PURPOSE: Enumerate the distinct ranks (values) of cards in blackjack.
0006 //
0007 //@CLASSES:
0008 //  bjgb::Rank: class representing the ranks of blackjack cards
0009 //
0010 //@DESCRIPTION: This component provides a class, 'bjgb::Rank', and its
0011 // associated user-defined literal (UDL) operator that enumerate the ten
0012 // distinct card ranks (or values) in blackjack.
0013 //
0014 /// Literals
0015 ///--------
0016 //..
0017 //  Name   Value
0018 //  ----   --------------------------------------------
0019 //   A_R     1 (Ace; alias for 1_R)
0020 //   2_R     2
0021 //   3_R     3
0022 //   4_R     4
0023 //   5_R     5
0024 //   6_R     6
0025 //   7_R     7
0026 //   8_R     8
0027 //   9_R     9
0028 //   T_R    10 (Ten, Jack, Queen, King; alias for 10_R)
0029 //..
0030 //
0031 // Iteration over the ranks is supported by member function 'operator++()',
0032 // free 'operator<', and the 'end' class method.
0033 //
0034 /// Usage
0035 ///-----
0036 // Iterate over the range of ranks and print each:
0037 //..
0038 //  for (Rank r = A_R; r != Rank::end(); ++r) {
0039 //      if (r != A_R) {
0040 //          std::cout << ' ';
0041 //      }
0042 //      std::cout << r;
0043 //  }
0044 //
0045 //  std::cout << '\n';
0046 //..
0047 // The above prints the following to 'std::cout':
0048 //..
0049 //  A 2 3 4 5 6 7 8 9 T
0050 //..
0051 
0052 #include <cassert>
0053 #include <iosfwd>
0054 
0055 namespace bjgb {
0056 
0057 class Rank;
0058 
0059 // UDL OPERATORS
0060 inline namespace literals {
0061 inline namespace RankLiterals {
0062 constexpr Rank operator""_R(unsigned long long value);
0063 } // namespace RankLiterals
0064 } // namespace literals
0065 
0066 // ==========
0067 // class Rank
0068 // ==========
0069 
0070 class Rank {
0071     // This class represents the ranks of cards in blackjack.  Instances of
0072     // this class can be created only via either the associated UDL operator,
0073     // '_R', or the 'end' class method.
0074 
0075     // DATA
0076     int d_value; // the range '[1 .. 10]' corresponds to A, 2, ..., T; 11 is
0077                  // used to represent the one-past-the-end value for iterating
0078 
0079     // FRIENDS
0080     friend constexpr Rank RankLiterals::operator""_R(unsigned long long);
0081     friend bool operator==(const Rank&, const Rank&);
0082     friend bool operator!=(const Rank&, const Rank&);
0083     friend bool operator<(const Rank&, const Rank&);
0084 
0085   private:
0086     // PRIVATE CREATORS
0087     explicit constexpr Rank(int value);
0088     // Create a rank object having the specified 'value'.  The behavior is
0089     // undefined unless '1 <= value' and 'value <= 11'.  Note that
0090     // 'Rank(11)' provides the value for 'Rank::end()'.
0091 
0092   public:
0093     // CLASS METHODS
0094     static Rank end();
0095     // Return a rank object having the one-past-the-end value.
0096 
0097     // CREATORS
0098     Rank() = delete;
0099 
0100     Rank(const Rank& original) = default;
0101     // Create a rank object having the same value as that of the specified
0102     // 'original' object.
0103 
0104     ~Rank() = default;
0105     // Destroy this rank object.
0106 
0107     // MANIPULATORS
0108     Rank& operator=(const Rank& rhs) = default;
0109     // Assign to this object the value of the specified 'rhs' rank, and
0110     // return a reference providing modifiable access to this object.
0111 
0112     Rank& operator++();
0113     // Increment this rank and return a non-'const' reference to this
0114     // object.  The behavior is undefined unless '*this < Rank::end()' on
0115     // entry.  Note that, for example:
0116     //..
0117     //  ++(5_R) == 6_R && ++(T_R) == Rank::end();
0118     //..
0119 
0120     // ACCESSORS
0121     int value() const;
0122     // Return the integral value of this rank.  The behavior is undefined
0123     // unless '*this != Rank::end()'.
0124 };
0125 
0126 // FREE OPERATORS
0127 bool operator==(const Rank& lhs, const Rank& rhs);
0128 // Return 'true' if the specified 'lhs' and 'rhs' ranks have the same
0129 // value, and 'false' otherwise.  Two 'Rank' objects have the same value if
0130 // they correspond to the same UDL in the range '[A_R .. T_R]' or both have
0131 // the same value as 'Rank::end()'.
0132 
0133 bool operator!=(const Rank& lhs, const Rank& rhs);
0134 // Return 'true' if the specified 'lhs' and 'rhs' ranks do not have the
0135 // same value, and 'false' otherwise.  Two 'Rank' objects do not have the
0136 // same value if they correspond to different UDLs in the range
0137 // '[A_R .. T_R]' or one of them, but not both, has the same value as
0138 // 'Rank::end()'.
0139 
0140 bool operator<(const Rank& lhs, const Rank& rhs);
0141 // Return 'true' if the specified 'lhs' rank is less than the specified
0142 // 'rhs' rank, and 'false' otherwise.  All ranks corresponding to UDLs in
0143 // the range '[A_R .. T_R]' compare less than 'Rank::end()'.
0144 
0145 std::ostream& operator<<(std::ostream& stream, const Rank& rank);
0146 // Write the string representation of the specified 'rank' to the specified
0147 // output 'stream' in a single-line format, and return a reference to
0148 // 'stream'.
0149 
0150 // ============================================================================
0151 //                              INLINE DEFINITIONS
0152 // ============================================================================
0153 
0154 // ----------
0155 // class Rank
0156 // ----------
0157 
0158 // PRIVATE CREATORS
0159 inline constexpr Rank::Rank(int value): d_value(value)
0160 {
0161     assert(1 <= value);
0162     assert(value <= 11);
0163 }
0164 
0165 // CLASS METHODS
0166 inline Rank Rank::end()
0167 {
0168     return Rank(11);
0169 }
0170 
0171 // MANIPULATORS
0172 inline Rank& Rank::operator++()
0173 {
0174     assert(d_value <= 10);
0175 
0176     ++d_value;
0177 
0178     return *this;
0179 }
0180 
0181 // ACCESSORS
0182 inline int Rank::value() const
0183 {
0184     assert(d_value <= 10);
0185 
0186     return d_value;
0187 }
0188 
0189 } // namespace bjgb
0190 
0191 // FREE OPERATORS
0192 inline bool bjgb::operator==(const Rank& lhs, const Rank& rhs)
0193 {
0194     return lhs.d_value == rhs.d_value;
0195 }
0196 
0197 inline bool bjgb::operator!=(const Rank& lhs, const Rank& rhs)
0198 {
0199     return lhs.d_value != rhs.d_value;
0200 }
0201 
0202 inline bool bjgb::operator<(const Rank& lhs, const Rank& rhs)
0203 {
0204     return lhs.d_value < rhs.d_value;
0205 }
0206 
0207 // UDL OPERATORS
0208 inline constexpr bjgb::Rank bjgb::RankLiterals::operator""_R(unsigned long long value)
0209 {
0210     assert(1 <= value);
0211     assert(value <= 10);
0212 
0213     return Rank(value);
0214 }
0215 
0216 namespace bjgb {
0217 inline namespace literals {
0218 inline namespace RankLiterals {
0219 constexpr Rank A_R = 1_R;
0220 constexpr Rank T_R = 10_R;
0221 } // namespace RankLiterals
0222 } // namespace literals
0223 } // namespace bjgb
0224 
0225 #endif