I’d like to compare STL strings that are allocated with different allocators, e.g. an ordinary std::string with a string using a custom STL allocator. Unfortunately, it seems that usual operator==() doesn’t work in this case:
// Custom STL allocator to allocate char's for string class
typedef MyAllocator<char> MyCharAllocator;
// Define an instance of this allocator
MyCharAllocator myAlloc;
// An STL string with custom allocator
typedef std::basic_string
<
char,
std::char_traits<char>,
MyCharAllocator
>
CustomAllocString;
std::string s1("Hello");
CustomAllocString s2("Hello", myAlloc);
if (s1 == s2) // <--- ERROR: doesn't compile
...
In particular, MSVC10 (VS2010 SP1) emits the following error message:
error C2678: binary ‘==’ : no operator found which takes a left-hand
operand of type ‘std::string’ (or there is no acceptable conversion)
So, a lower-level (less readable) code like this:
if (strcmp(s1.c_str(), s2.c_str()) == 0)
...
should be used.
(This is also particularly annoying in cases where e.g. there are std::vector‘s of differently-allocated strings, where the usual simple v[i] == w[j] syntax can’t be used.)
This doesn’t seem very good to me, since a custom allocator changes the way string memory is requested, but the interface of a string class (including comparison with operator==()) is independent from the particular way a string allocates its memory.
Is there something I am missing here?
Is it possible to keep the C++ high-level interface and operator overloads in this case?
Use
std::lexicographical_comparefor less-than comparison:For equality comparison you can use
std::equal:Alternatively, you can just fall back on
strcmp(or actuallymemcmp, since that has the correct semantics; remember that the C++ string is more general than a C string), as you suggested, which can potentially employ some lower-level magic like comparing an entire machine word at a time (though the above algorithm may also be specialized thus). Measure and compare, I’d say. For short strings, the standard library algorithms are at least nicely self-descriptive.Based on @Dietmar’s idea below, you could wrap those functions into a templated overload:
Usage example:
In fact, you could define such an overload for most standard containers. You could even template it on a template, but that would be extreme.