Skip to content

Instantly share code, notes, and snippets.

@crcrpar
Created July 18, 2019 03:46
Show Gist options
  • Select an option

  • Save crcrpar/48940bec3e8d41c4bf0b1459a1085126 to your computer and use it in GitHub Desktop.

Select an option

Save crcrpar/48940bec3e8d41c4bf0b1459a1085126 to your computer and use it in GitHub Desktop.
Curiously Recurring Template Pattern
/*
* Introduction to Curiously Recurring Template Pattern
*
* Ref: https://theolizer.com/cpp-school2/cpp-school2-19/
*/
#include <iostream>
#include <iomanip>
#include <cstdint>
#include <tuple>
#define isDebug() 0
#if isDebug()
// This is a big picture.
template <class tDerived>
class CrtpBase {};
class CrtpDerived : CrtpBase<CrtpDerived> {};
#endif
template <class tDerived>
struct CompareBase {
// based on operator<
bool operator>(tDerived const& iRhs) const {
return (iRhs < static_cast<tDerived const&>(*this));
}
bool operator==(tDerived const& iRhs) const {
return !(static_cast<tDerived const&>(*this) < iRhs) && !(iRhs < static_cast<tDerived const&>(*this));
}
bool operator !=(tDerived const& iRhs) const {
return (static_cast<tDerived const &>(*this) < iRhs) || (iRhs < static_cast<const &>(*this));
}
bool operator<=(tDerived const& iRhs) const {
return !(iRhs < static_cast<tDerived const&>(*this));
}
bool operator>=(tDerived const& iRhs) const {
return !(static_cast<tDerived const&>(*this) < iRhs);
}
};
// struct Date {
// uint16_t mYear;
// uint8_t mMonth;
// uint8_t mDay;
//
// Date(uint16_t iYear, uint8_t iMonth, uint8_t iDay)
// : mYear(iYear), mMonth(iMonth), mDay(iDay) {}
//
// bool operator<(Date const& iRhs) const {
// return std::tie(mYear, mMonth, mDay) < std::tie(iRhs.mYear, iRhs.mMonth, iRhs.mDay);
// }
//
// // Deduce from operator<
// bool operator>(Date const& iRhs) const { return iRhs < *this; }
// bool operator==(Date const& iRhs) const { return !(*this < iRhs) && !(iRhs < *this); }
// bool operator!=(Date const& iRhs) const { return (*this < iRhs) || (iRhs < *this); }
// bool operator<=(Date const& iRhs) const { return !(iRhs < *this); }
// bool operator>=(Date const& iRhs) const { return !(*this < iRhs); }
// };
struct Date : public CompareBase<Date> {
uint16_t mYear;
uint8_t mMonth;
uint8_t mDay;
Date(uint16_t iYear, uint8_t iMonth, uint8_t iDay)
: mYear(iYear), mMonth(iMonth), mDay(iDay) {}
bool operator<(Date const& iRhs) const {
return std::tie(mYear, mMonth, mDay) < std::tie(iRhs.mYear, iRhs.mMonth, iRhs.mDay);
}
};
struct SizeString : public std::string, public CompareBase<SizeString> {
using std::string::string;
bool operator<(SizeString const& iRhs) const {
return size() < iRhs.size();
}
};
// After the above definitions, we wanted to define order btwn strings by their length.
// struct SizeString : public std::string {
// using std::string::string;
//
// bool operator<(SizeString const& iRhs) const {
// return size() < iRhs.size();
// }
/* This repetitive definition is tedious and easy to cause mistakes.
* Here, we can utilize CRTP.
* bool operator>(SizeString const& iRhs) const { return iRhs < *this; }
* bool operator==(SizeString const& iRhs) const { return !(*this < iRhs) && !(iRhs < *this); }
* bool operator!=(SizeString const& iRhs) const { return (*this < iRhs) || (iRhs < *this); }
* bool operator<=(SizeString const& iRhs) const { return !(*this < iRhs); }
* bool operator>=(SizeString const& iRhs) const { return !(iRhs < *this); }
*/
// };
int main() {
Date aToday(2019, 7, 18);
Date aTomorrow(2019, 7, 19);
std::cout << std::boolalpha;
std::cout << "aToday < aTomorrow = " << (aToday < aTomorrow) << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment