views:

223

answers:

2

I'm making my own string class and I was wondering if there's any way to replace the compiler behaviour around " characters.
As I said in the title I'd like to make it so that CString a = "Hello " + "World!"; would actually work and not give a compiler error telling that it can't add 2 pointers. My string class automatically converts to char* when needed and thus writing printf(a) would not break the code.
I'm sure this is a rather weird question but if it's possible I'd really like to know how to do it.
Thank you very much

+6  A: 

You can't do exactly that because you can only overload operators for class types, and a string literal does not have class type.

You can take advantage of the concatenation of string literals that takes place during preprocessing:

CString a = "Hello " "World!";

or you can create a CString temporary and append to it:

CString a = CString("Hello ") + "World!";

or you could have a CString constructor that takes more than one argument:

CString a("Hello ", "World!");
James McNellis
But you can do the temporary one already with std::string str(std::string("Hello") + "World");!!!!
David Relihan
@David: Yes; and...? I'm not sure I see what you're getting at.
James McNellis
The OP can't possibly improve on std::string in any case, so the whole exercise is just for learning. There's no point in comparing his class to std::string.
DeadMG
I can allready do CString a = CString("Hello")+" World"; but I was just looking to make it even simpler. It's not a necesity but more like a personal taste. I did know it was hard to do/impossible but I was just looking for some clarification.
Sanctus2099
+5  A: 

The right answer

No. You cannot overload operators for built-ins, such as pointers.

James McNellis already answered the question, so I won't elaborate.

A possible alternative...

(I use std::string because I have no info on your in-house string)

Using a typedef will add some sugar to your syntax:

typedef std::string S_ ;

int main(int argc, char* argv[])
{
   std::string s = S_("Hello") + S_(" World") ;

   std::cout << "s : " << s << std::endl ;

   return 0 ;
}

But then, I wouldn't pollute the global namespace with a two-characters symbol just for a little sugar... And as far as I know, the code is inefficient (two string objects created, plus one temporary, without guarantee the compiler will optimize it all away...)

For curiosity's sake...

As a curiosity, by wrapping the string into a thin class, you can "add" those two pointers.

First, let's create the wrapper :

class StringThinWrapper
{
   public :

      StringThinWrapper(const char * p) : m_p(p) {}
      operator const char * () const { return m_p ; }

   private :
      const char * const m_p ;
} ;

As you can see, it's both inlined, and will do nothing... Still, it's able to cast itself into a const char * pointer (this kind of hack is dangerous, so be sure it's what you want to do).

Then, for this wrapper, let's overload the addition operator :

inline std::string operator + (const StringThinWrapper & lhs, const StringThinWrapper & rhs)
{
   std::string s(lhs) ;
   s += rhs ;
   return s ;
}

And now, let's write a main function using the wrapper, typedefed for ease of use :

typedef StringThinWrapper S_ ;

int main(int argc, char* argv[])
{
   std::string s = S_("Hello") + S_(" World") ;

   std::cout << "s : " << s << std::endl ;

   return 0 ;
}

Which compiles and gives the following result :

s : Hello World

Disclaimer: I just wanted to play with the idea your question gave me, and share it with you. Don't apply this kind of code just because you can. Indeed, this code should be refined to cover all cases efficiently before even being used, and even then, a simple typedef std::string S_ ; would be better IMHO.

AFAIK, I wouldn't use it because I'm happy with the current STL API.

And what about C++0x ?

In C++0x, you'll be able to create your own literals. The code will be kinda like :

std::string operator "str"(const char * p)
{ 
    return std::string(p); 
}

And you'll use it so :

int main(int argc, char * argv[])
{
   std::string s = "Hello"str + " World"str ;

   std::cout << "s : " << s << std::endl ;

   return 0 ;
}

For more information, see the following SO question: http://stackoverflow.com/questions/237804.

paercebal
I see your point but using _S("some string") is roughly just the same as writing CString("some string"). I was just looking for a way to eliminate that completly. I for one don't like STL and that's why I'm making my own little classes. I heard about C++0x but never got my hands on it yet. It's indeed a intresting approach the thing with "literal overloading"(I hope this is technically correct). Would it be possible to maybe replace the "" literal and thus make my code work?
Sanctus2099
@Sanctus2099 : Of course it is the same, but the `S_` notation is 5 chars shorter, and thus, somewhat more pleasing to read ... Again, James McNellis had it right : One can't overload the operators for built-ins, so both James' and my answer are the nearest approximation you'll have for your desired behaviour.
paercebal
@sanctus - don't use _S. It's a reserved name. No, you won't be able to replace "" to make your code work in 0x.
Noah Roberts
@Sanctus - I agree with Noah Roberts. It's why I used `S_` instead of `_S` ...
paercebal