Strings In C++/CLI


A brief primer on how are string literals treated in C++/CLI ?

There has never been a type for string literals in C++. For instance, the type of 2 is int, the type of 's' is char. But there is no inherent type for "Hello World" in the language. It can accessed as char * or const char *. But that is not the type of the string literal. In the later years of evolution, the language provided the efficient and easy STL which has a std::string class for creating and managing strings. Even then, std::string is not its type. So when "Hello World" is passed as an argument for the method

int StringTest(std::string);

it requires a conversion (using the ctor). All I am trying to say, there is no inherent type for a string literal in C++, unlike in C# where the System.String is the type for string literals, methods can be invoked on string literals directly - "Hello World".Length gives 12.

C++/CLI being new and state-of-the-art might give you hope for what was not available in the language for years. Your eager expectations - System::String as type for string literals - have to be given up. I am sorry to disappoint you. Still there is no type for string literals. But since C++/CLI is a secular [managed/unmanaged] programming language, there are some interesting things to be noted.

String literals in C++/CLI have the flexibility of associating themselves with (the closest) managed or unmanaged types based on the context, and of course, managed types given the priority. So "Hello World" can be treated as System::String or const char * or char *. Let us learn that with an example:-

int StringTest(const char *);
int StringTest(System::Object^ strObject);
int StringTest(System::String^ clrString);
int StringTest(std::string stdString);

and guess to which of the above methods will the following call bind to ?

StringTest("Hello World");

The above call will bind to the System::String^ overload. As I said earlier, managed types are given higher priorities in string contexts. In the absence of the System::String^ overload, the call will be bound to the overload with System::Object^ as argument. And the unmanaged const char * will be considered in the absence of both the managed types. Besides that, even among managed types, only those that are found closest to adopt string literals are considered; when none are found compatible, const char * overload takes precedence. And types that require conversion (using conversion operators or explicit ctors) are the last options, which is the case with the std::string overload.

So what do you think will happen with the following line of code - compilation error, run-time error, runs fine ?

int hc = "Hello World"->GetHashCode();

Guesses apart, the above line of code will result in a compilation error. No, don't try to replace the -> with . (dot). It is not that. The compiler finds no context like a method call to match the type of the string literal to an existing type, which should convince you that there is no inherent compiler type for string literals. Period. All the different flavors of type matching for string literals may help us build a C++ world where "Hello World"s are one day System::String. So try to write code (as much) that binds to System::String.