Skip to content

Instantly share code, notes, and snippets.

@elbeno
Created September 29, 2017 14:21
Show Gist options
  • Save elbeno/e091904904331fcdcd0389f51152ad82 to your computer and use it in GitHub Desktop.
Save elbeno/e091904904331fcdcd0389f51152ad82 to your computer and use it in GitHub Desktop.
Herb Sutter's SCM Challenge at CppCon 2017 - my winning code
#include <algorithm>
#include <iostream>
#include <type_traits>
class CIString {
std::string s;
public:
CIString(std::string _s): s(_s) {};
// functions want to be free!
friend inline bool operator==(const CIString& x, const CIString& y);
friend inline bool operator==(const char* x, const CIString& y);
friend inline bool operator==(const CIString& x, const char* y);
friend inline bool operator<(const CIString& x, const CIString& y);
friend inline bool operator<(const char* x, const CIString& y);
friend inline bool operator<(const CIString& x, const char* y);
};
// case insensitive comparison function objects...
// insert arbitrary complexity here
struct ci_compare_equal
{
bool operator()(char x, char y) const
{
return std::toupper(x) == std::toupper(y);
}
};
struct ci_compare_less
{
bool operator()(char x, char y) const
{
return std::toupper(x) < std::toupper(y);
}
};
// operator== and operator<
inline bool operator==(const CIString& x, const CIString& y)
{
return std::equal(x.s.cbegin(), x.s.cend(),
y.s.cbegin(), y.s.cend(), ci_compare_equal{});
}
inline bool operator<(const CIString& x, const CIString& y)
{
return std::lexicographical_compare(x.s.cbegin(), x.s.cend(),
y.s.cbegin(), y.s.cend(), ci_compare_less{});
}
// other comparison operators in terms of operator== and operator<
// (or use std::rel_ops?)
inline bool operator!=(const CIString& x, const CIString& y)
{
return !(x == y);
}
inline bool operator>(const CIString& x, const CIString& y)
{
return y < x;
}
inline bool operator<=(const CIString& x, const CIString& y)
{
return !(y < x);
}
inline bool operator>=(const CIString& x, const CIString& y)
{
return !(x < y);
}
// now the same for comparing one way around...
inline bool operator==(const char* x, const CIString& y)
{
const auto s = std::string_view(x);
return std::equal(s.cbegin(), s.cend(),
y.s.cbegin(), y.s.cend(), ci_compare_equal{});
}
inline bool operator<(const char* x, const CIString& y)
{
const auto s = std::string_view(x);
return std::lexicographical_compare(s.cbegin(), s.cend(),
y.s.cbegin(), y.s.cend(), ci_compare_less{});
}
inline bool operator!=(const char* x, const CIString& y)
{
return !(x == y);
}
inline bool operator>(const char* x, const CIString& y)
{
return y < x;
}
inline bool operator<=(const char* x, const CIString& y)
{
return !(y < x);
}
inline bool operator>=(const char* x, const CIString& y)
{
return !(x < y);
}
// ...and the other way around
inline bool operator==(const CIString& x, const char* y)
{
const auto s = std::string_view(y);
return std::equal(x.s.cbegin(), x.s.cend(),
s.cbegin(), s.cend(), ci_compare_equal{});
}
inline bool operator<(const CIString& x, const char* y)
{
const auto s = std::string_view(y);
return std::lexicographical_compare(x.s.cbegin(), x.s.cend(),
s.cbegin(), s.cend(), ci_compare_less{});
}
inline bool operator!=(const CIString& x, const char* y)
{
return !(x == y);
}
inline bool operator>(const CIString& x, const char* y)
{
return y < x;
}
inline bool operator<=(const CIString& x, const char* y)
{
return !(y < x);
}
inline bool operator>=(const CIString& x, const char* y)
{
return !(x < y);
}
// I'm sure Herb will replace this all with half a dozen lines of spaceship operators :)
// You can use this function to write any tests you may want.
void tests() {
};
int main() {
tests();
// Added in the background
graderTests();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment