struct it_str_1
: public std::binary_function<std::string, std::string, bool> {
struct it_char {
const std::ctype<char>&ct;
it_char(const std::ctype<char>& c): ct(c) {}
bool operator()(char x, char y) const {
return ct.toupper(x) < ct.toupper(y);
}
};
std::local loc;
const std::ctype<char>& ct;
it_str_1(const std::locale& L = std::local::classic())
: loc(l), ct(std::use_facet<std::ctype<char> >(loc)) {}
bool operator()(const std::string&x, const std::string& y) const {
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), it_char(ct));
}
};
we are calling toupper in a loop, and the C++ standard requires toupper to make a virtual function call. Some optimizers may be smart enough to move the virtual function overhead out of the loop, but most aren’t.
another one of ctype’s memeber functions
const char* ctype<char>::toupper(char* f, chr* i) const
using it to compare two strings would require copying both strings to buffers and then converting the buffers to uppercase. They can not be fixed size arrays, but dynamic arrays would require an expensive memory allocation.
struct it_str_2:
public std::binary_function<std::string, std::string, bool> {
struct it_char {
const char* tab;
it_char(const char* t) : tab(t) {}
bool operator() (char x, char y) const {
return tab[x - CHAR_MIN] - tab[y - CHAR_MIN];
}
};
char tab[CHAR_MAX - CHAR_MIN + 1];
it_str_2(const std::locale& L = std::locale::classic()) {
const std::ctype<char>& ct = std::use_facet<std::ctype<char> >(L);
for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) {
tab[i - CHAR_MIN] = (char)i;
ct.toupper(tab, tab + (CHAR_MAX - CHAR_MIN + 1);
}
bool operator()(const std::string& x, const std::string& y) const {
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), it_char(tab));
}
};