My main suggestion for this code is for the `helper` function. It's not a good idea to only compare a few selected strings from the set of all interesting strings. It's far more efficient to just have a list of strings that are already ordered, and then ensure that this ordering is represented by the `<=>` operator under test. To do this, each element should be compared to each element, including itself. The code I usually use to do this is: ~~~c++ #include <cassert> #include <string> #include <vector> #include <iostream> int sign(int i) { return i < 0 ? -1 : i > 0 ? +1 : 0; } template<typename T> int spaceship(T a, T b) { return a < b ? -123 : a > b ? +123 : 0; } std::string op(int cmp) { return cmp < 0 ? "<" : cmp > 0 ? ">" : "=="; } template<typename T> void test_spaceship(const std::vector<T> &elements) { bool error = false; for (std::size_t i = 0; i < elements.size(); ++i) { for (std::size_t j = 0; j < elements.size(); ++j) { int expected = spaceship(i, j); int actual = spaceship(elements[i], elements[j]); if (sign(expected) != sign(actual)) { std::cerr << __func__ << ":\n"; std::cerr << " expected " << elements[i] << " " << op(expected) << " " << elements[j] << "\n"; std::cerr << " but got " << elements[i] << " " << op(actual) << " " << elements[j] << "\n"; error = true; } } } std::flush(std::cerr); assert(!error); } int main() { std::vector<std::string> elements{ "", "first", "second", "zfourth", // intentionally in the wrong order "third", "zzfifth" }; test_spaceship(elements); std::cout << "ok\n"; std::string s; std::getline(std::cin, s); } ~~~ Of course you would have to adjust the code a bit to test your `Strong_String` instead of my `std::string`, but the general idea should get clear. If you have some strings that are considered equal by your operator `<=>`, you would have to adjust the above code to have a `std::vector<std::vector<T>>`, but that should be equally easy. ---- My other favorite topic is the [cctype header](https://stackoverflow.com/questions/7131026/is-it-safe-to-call-the-functions-from-cctype-with-char-arguments) since you must never feed a plain character to functions like `isalnum` or `toupper`. Furthermore by doing this, you limit your program to 8-bit character sets, unless `CHAR_BIT` is greater than 8 on your machine, and chances are small for that. You should rather treat your strings as Unicode strings, and that brings a whole new topic of decisions, such as sorting strings from different scripts and languages. But that's still better than being caught in the 1990s with their limited [code pages](https://en.wikipedia.org/wiki/Code_page).