lostbits
lostbits

Reputation: 1054

string concatenation doesn't work as expected

(win7; gcc 4.8.2 (cygwin))

The code fragment below yields count error Pointer\\ instead of ( "Pointer" ). Is there anything I can do to get the correct result?

  virtual string toString() const { 
     return "Pointer";
  }
  virtual string write() const {
     string str = "( " + '"' + toString() + '"' + " )";
     return str;
  }; 

Upvotes: 0

Views: 419

Answers (2)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385108

First, let's clear up a few things:

+-------------+----------------+-----------------------+
| Expression  | Type           | Type as operator arg  |
+-------------+----------------+-----------------------+
|  toString() |  std::string   |  std::string          |
|  "( "       |  char const[3] |  char const*          |
|  '"'        |  char          |  char                 |
+-------------+----------------+-----------------------+

These are not all "strings".

The main issue here is that "( " + '"' does not do what you think it does. "Adding" a char to a const char* does not build a larger string; it adds a number to the string literal's pointer value. In doing this, you make a new pointer that points to… well… nowhere useful. In fact you're invoking undefined behaviour by incrementing the pointer so far.

It's a bit like this:

char const* whatYouAreDoing()
{
   char const* a = "( ";
   char b = '"';

   int c = b;
   assert(c == 34);  // assuming ASCII 
   a += c;           // whoops!

   return a;         // this pointer is now nonsense
}

Generally, if you want to "build" a string, you can use stream formatting:

virtual string write() const
{
   std::stringstream ss;
   ss << "( " << '"' << toString() << '"' << " )";
   return ss.str();
}

Or, in this case, since you actually don't need all those literals, the following will be fine:

virtual string write() const
{
   return "( \"" + toString() + "\" )";
}

Upvotes: 4

Tobias
Tobias

Reputation: 5198

You should use a string as first summand and to be safe you also need some braces. Make sure that all summands are strings (maybe after conversion).

Okay, that is not entirely true, also operators like + (std::string&, consts char*) are fine if such things exist. But, I hope you get the idea. You have to make sure that the intended +-operations are used, i.e. that ones from the string-class.

See the following example:

#include <string>
#include <iostream>

using namespace std;

string toString() { 
    return "Pointer";
}
string write() {
    string str = string("( ") + '"' + (toString() + '"') + " )";
    return str;
};

int main()
{
    std::cout << "Test:>>" << write() << "<<\n";
  return 0;
}

Upvotes: 0

Related Questions