I would define a comparator like this:
#include <boost/algorithm/string/predicate.hpp>
struct ci_compare {
bool operator()(std::string_view const& a,
std::string_view const& b) const {
return boost::ilexicographical_compare(a, b);
}
};
Then you can use it with your datastructure of choice:
std::set<std::string, ci_compare> keys;
Live On Compiler Explorer
#include <boost/algorithm/string/predicate.hpp>
struct ci_compare {
bool operator()(std::string_view const& a,
std::string_view const& b) const {
return boost::ilexicographical_compare(a, b);
}
};
#include <boost/core/demangle.hpp>
#include <fmt/ranges.h>
#include <map>
#include <set>
using namespace std::string_literals;
auto dump(auto const& data) {
fmt::print("---\nData structure: {}\nData: {}\nContains 'three'? {}\n",
boost::core::demangle(typeid(data).name()), data,
data.contains("three"));
}
int main() {
dump(std::set{{"hellO", "hEllo", "world"}, ci_compare{}});
dump(std::map<std::string, int, ci_compare>{
std::pair{"one"s, 1}, {"TWO"s, 2}, {"Three", 3}});
}
Prints
---
Data structure: std::set<char const*, ci_compare, std::allocator<char const*> >
Data: {"hellO", "world"}
Contains 'three'? false
---
Data structure: std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, ci_compare, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >
Data: {("one", 1), ("Three", 3), ("TWO", 2)}
Contains 'three'? true