2

I'm trying to compare libpqxx c_str values.

If I try to compare them directly, result1[0][0].c_str() == result2[0][0].c_str(), for example, they do not return true when they have the same string values. The only way to compare them properly is to use strcmp.

However, if I'm comparing a libpqxx c_str to a std::string with strcmp, the compiler complains that an argument of strcmp cannot be a std::string, yet most strangely of all to me: if I compare something like result1[0][0].c_str() == some_std_string, the comparison will return true if they possess the same value, false otherwise.

Why is this? Is this something particular to libpqxx? If not, is this standard behavior?

  • 2
    `result1[0][0].c_str() == result2[0][0].c_str()` Well yeah, those are two different pointers. – ta.speot.is May 17 '14 at 03:55
  • 2
    @Gracchus, it's worth noting that even if `string` didn't have an `operator==` for char pointers, the mere fact that a `const char*` can be implicitly made into a `string` means that it would work anyways. Seeing that no `operator==` exists, the compiler would look for a way to implicitly convert the `const char*` into a `string`, would find the non-`explicit` string constructor that accepts a single `const char*`, and use it. – zneak May 17 '14 at 04:08

2 Answers2

10

It happens because std::string is a class, while const char* (the type returned by c_str) is, well, a pointer type. Comparing pointers returns true if the pointers point to the same memory location. Classes, on the other hand, can define what equality means to them.

Since strings and const char* are fairly analogous, the string class defines a method of comparing string objects to const char* pointers. It also defines how to convert a char pointer into a string. However, this is essentially a one-way street, as it does not define how to create a const char* from a string using mere operators or implicit conversions. This is why you can't use strcmp on them.

Strcmp is a function from the C standard library. C has no classes and types cannot define basic behavior like C++ classes can. Therefore, C defines a bunch of function to deal with char pointers, and char pointers only.

This kind of inconsistency between char pointers and strings isn't limited to equality. For instance, std::string supports concatenation with the + operator: this means that string + string works, const char* + string works, string + const char* works, but const char* + const char* results in a compile-time error, because pointers don't define this kind of operation.

zneak
  • 134,922
  • 42
  • 253
  • 328
2

Just use c_str(), too!

if (strcmp(result1[0][0].c_str(), some_std_string.c_str()) == 0)
{
    ...

or use operator == of std::string

if (result1[0][0].c_str() == some_std_string)
ikh
  • 10,119
  • 1
  • 31
  • 70
  • Thank you for giving me a aesthetically consistent method! –  May 17 '14 at 03:58
  • @Gracchus plz choose my answer if it helps you >o< Btw, Doesn't `string` of lipqxx support `operator ==`? How bad... – ikh May 17 '14 at 04:00
  • you should at least add some words about the implicit cast (via ctr) in the second case – Wolf Jun 02 '14 at 13:19
  • implicit cast? where?? – ikh Jun 03 '14 at 14:59
  • Do you mean... result1[0][0].c_str() will be implicit-cast? No, `std::string` has not only `bool operator ==(const std::string&, const std::string&)`, but also `bool operator ==(const char*, const std::string&)` and `bool operator ==(const std::string&, const char*)` – ikh Jun 03 '14 at 23:17