Probably many people have already encountered the following problem:
| CODE |
#include<string> class MyClass{ std::string str; public: set_str(const std::string&s){str=s;} }; |
The code above works fine as long as s is a std::string but what if its a char* Example:
| CODE |
MyClass my; my.set_str("Hello"); |
That will not work because "hello" is not of type string. There are 3 solutions to this problem:
- Make 2 versions of set_str. One with char* and one with std::string&. But this is error prone because you will have 2 maintaine 2 functions. Also you will have to overload anoter version for char. To put it simple it's too much code for a simple task.
- Take the string by value. This way the copyconstructor will build a string based on "Hello". But there's the downside of that useless overheat. Also many compilers will no longer inline it.
- The best solution in my eyes is the use of a template:
| CODE |
#include<string> class MyClass{ std::string str; public: template<typename Str> set_str(const Str&s){str=s;} }; |
This will automaticaly overload set_str() for all arguments supported by string::operator=. Also set_str is inlined and the C++ standard does not requirer that references are internaly pointers, so with most compilers you will end up with s being direktly passed to string::operator=, meaning without any overheat although you still have encapusated str but without any overhead or lot of overloading work. Also if a new version of string::operator= would be added in futur your code will automaticaly support it.
Another problem that you often encounter is that you want to write a function that writes to a char array and you risk to run over the border. The most obvious solution would be to somewhere keep track of the max size of the char, but this causes runtime overhead and often not simple to use. If you use dynamic arrays there's no other way, but what about stack arrays? Compile-time size info exists but most people don't know how to use it. This will not work:
| CODE |
void func(char a[]) { sizeof(a); } |
Because char a[] is a synomime for char*a and char* is no array but a pointer (which may but doesn't have to be a pointer to an array). You can also requier that a array to a certain function has a certain size:
| CODE |
void func(char a[5]) { //size is 5 } |
But it's not possible to overload a 1000 function to allow the use of most array sizes. Also imagine the size that would need. The solution again is called template. Example:
| CODE |
#include"string.h" template<unsigned int size> inline void copy_char_arr(char to[size],char*from) { strncpy(to,from,size-1); } |
The size of from is not needed because it's assumed to be null terminated. Also I have used inline to remove overheat as far as possible. All in all this function works just like strcpy but with the exeption that you will not run over the border of to. Dynamic arrays are obviously not supported because there's no compile-time size info so here we will have to assume that the size is big enough:
| CODE |
#include"string.h" template<unsigned int size> inline void copy_char_arr(char to[size],char*from) { strncpy(to,from,size-1); } inline void copy_char_arr(char*to,char*from) { strcpy(to,from); } |
If you use the 2 functions above the compiler will make sure that, as long as he can, that you do not overwrite the border. An input stream (ex:cin) uses this so you do not need to worry that it's writes over the border of char array of which you have compile time size info.
Another problem I have sometimes seen is that people don't know how to use TCHAR with std::string. And though the solution is suprisingly simple:
| CODE |
#include<windows.h> #include<string> typedef std::basic_string<TCHAR> string; |
Thats all very cool. I like it.
Not sure about this part. Not that I disagree, I am just thinking out aloud.
| QUOTE |
Another problem I have sometimes seen is that people don't know how to use TCHAR with std::string. And though the solution is suprisingly simple:
| CODE | #include<windows.h> #include<string> typedef std::basic_string<TCHAR> string; |
|
What happens when TCHAR is wchar_t?
The following code will then fail to compile.
| CODE |
string myString("PLOP");
|
TCHAR also requires you to use the TEXT() macro around such strings. If you do that then it should work. So:
| CODE |
| string myString(TEXT("PLOP")); |
But I havn't test it but I would be surprised if it wouldn't work.
Yes. Now I remember. PS. Good work.