Home > Back-end >  Are two std::string_views refering to equal-comparing string literal always also equal?
Are two std::string_views refering to equal-comparing string literal always also equal?

Time:12-01

I have an unordered_map which is supposed to mimic a filter, taking key and value as std::string_view respectively. Now say I want to compare two filters that have the same key-value-pairs: Will they always compare equal?

My thought is the following: The compiler tries its best to merge const char*'s with the same byte information into one place in the binary, therefore within a specific translation unit, the string literal addresses will always match. Later I'm passing these addresses into the constructor of std::string_view. Naturally, as std::string_view doesn't implement the comparison operator==(), the compyler will byte-compare the classes and only when address and length match exactly, the std::string_views compare equal.

However: What happens if I instantiate a filter outside of this translation unit with exactly the same contents as the first filter and link the files together later? Will the compiler be able to see beyond the TU boundaries and merge the string literal locations as well? Or will the equal comparison fail as the underlying string views will have different addresses for their respective string literals?

Demo

#include <unordered_map>
#include <string_view>
#include <cstdio>


using filter_t = std::unordered_map<std::string_view, std::string_view>;

int main()
{
    filter_t myfilter = {{ "key1", "value"}, {"key2", "value2" }};

    filter_t my_second_filter = {{ "key1", "value"}, {"key2", "value2" }};

    if (my_second_filter == myfilter) {
        printf("filters are the same!\n");
    }
}

CodePudding user response:

Naturally, as std::string_view doesn't implement the comparison operator==(), the compyler will byte-compare the classes

That is never the case. If no operator== overload (or since C 20 a rewritten candidate overload of e.g. operator<=>) is available for a class type, then it is simply impossible to compare the type with ==.

Even for non-class types the built-in == never performs a bitwise/bytewise comparison of the object representation (i.e. the values of the bytes of storage occupied the object). The built-in == always performs a comparison of values held by the objects.

The only way to get bytewise comparison of the object representation is to explicitly have a operator== (or overload to which == can be rewritten) be defined to perform this comparison (e.g. by memcmp). Since that obviously wouldn't make sense for std::string_view (or most types), the standard library does not define std::string_view's operator== like that. It defines operator== (or operator<=> since C 20) instead to properly perform a comparison of the string it refers to, as a value, not as identity of a string literal or character array, see https://en.cppreference.com/w/cpp/string/basic_string_view/operator_cmp.

CodePudding user response:

The equal comparison match by content and not by address, so your equal operation will still work, but you might have two copies of your string, depending on your compilers optimizations.

  • Related