Component of the Week #31: bdlb_caselessstringview*
- Summary:
Provide support for case-insensitive keys for associative containers.
A relatively common requirement is to handle ASCII strings in a case-insensitive way.
The bdlb_caselessstringview* set of components provide mechanism to enable
(standard) associative and unordered-associative containers to use
case-insensitive strings as keys. These facilities work only on the
ASCII character set.
This suite includes three key components:
bdlb_caselessstringviewhash - A hash functor that generates case-insensitive hash codes
bdlb_caselessstringviewequalto - An equality comparison functor for case-insensitive string equality
bdlb_caselessstringviewless - A less-than comparison functor for case-insensitive string ordering
These functors work with both bsl::string and bsl::string_view types.
Note
While these components are very convenient, they do introduce some performance overhead compared to converting all strings to the same case before insertion and then using standard comparisons. The clarity and simplicity these components provide may outweigh the performance costs in some scenarios.
Here is an example use of these components:
// Case-insensitive unordered map (hash-based)
typedef bsl::unordered_map<bsl::string,
double,
bdlb::CaselessStringViewHash,
bdlb::CaselessStringViewEqualTo> StockPriceMap;
// Case-insensitive ordered map (tree-based)
typedef bsl::map<bsl::string,
double,
bdlb::CaselessStringViewLess> SortedStockPriceMap;
These container definitions create maps where keys like “AAPL”, “aapl”, and “Aapl” are all treated as identical.
Here’s a simple example using StockPriceMap:
// Create a case-insensitive stock portfolio
StockPriceMap portfolio;
// Add some stocks with prices
portfolio["AAPL"] = 192.75;
portfolio["MSFT"] = 425.22;
portfolio["GOOGL"] = 143.96;
// Case doesn't matter when looking up values
assert(portfolio["aapl"] == 192.75);
assert(portfolio["msft"] == 425.22);
assert(portfolio["GooGl"] == 143.96);
// Update a value using a different case
portfolio["aApL"] = 194.50;
assert(portfolio["AAPL"] == 194.50);
// Check if a key exists in the map
assert(portfolio.count("msft") == 1);
assert(portfolio.count("TSLA") == 0);
Finally, notice that these components also support the heterogeneous lookup feature introduced in C++14, allowing you to look up strings using different string-like types without a performance penalty:
StockPriceMap portfolio;
portfolio["AAPL"] = 192.75;
// Look up using different string-like types
const char* literal = "aapl";
bsl::string_view view("AaPl");
bsl::string str("Aapl");
// All these lookups succeed
assert(portfolio[literal] == 194.50);
assert(portfolio[view] == 194.50);
assert(portfolio[str] == 194.50);
For more details, see:
bdlb_caselessstringviewhash component documentation
bdlb_caselessstringviewequalto component documentation
bdlb_caselessstringviewless component documentation