The String Literal Returns


In the last entry, I celebrated what I felt was an elegant solution to the problem of the string literal in the context of overload function resolution. But it turns out there is another area in which the string literal proves problematic. Who would have thought such a foobar kind of entity could cause so much trouble? It’s these kinds of ambushes that makes the extension of a language so unpredictable.  

 

So, here’s the problem.

 

            throw “fritz”;

 

what does the compiler do? it has to set everything up at compile-time, then it actually gets handled by a run-time library that makes use of a limited form of type reflection to figure the kind of object having been thrown.

 

there’s no context, really. we don’t know if the person is going to catch x, y, or z, so we can’t know what to throw in any particular instance. this is all set up at compile-time.

 

Now, here is the rub:

 

          void f()

           {

                     try { g(); }

                     catch ( String^ s ) {}

                     catch ( const char* pcs ) {}

            }

 

            void g()

             {

                     throw “fritz”;

              }

 

What gets caught? what an impossible question. one could argue if we are compiling for the CLR, then String^ should match, and if we are in native, and so on. But there’s no reason to believe that just because we are compiling for the CLR, people are using String and not just const char*.

 

So, a string literal is thrown as a type const char*, not as String^.  My first reaction was, gosh, that’s terrible. Then, I thought, what am I thinking? It seems a very small matter. It’s not even something I would run into since I don’t throw anything but class objects. I just add it for completeness.

 

I think if this bothers you, then you are bothered by our entire effort. Just as a sounding. That is, not everybody is happy with our work on C++/CLI. There are some folks out there that feel concern that we are somehow messing with their language, and we shouldn’t be allowed to do that.

 

we aren’t doing it that way at all. We have really wanted to be good c++ citizens while being excellent Microsoft employees. I have never felt any pressure to compromise either while I have been here. We have had an extraordinary degree of freedom not simply in our design, but in our being able to reach out and work with the general c++ community. this language is a coalition. I think we have all wanted to put the best face on C++ in what we regard as an otherwise hostile environment for C++. We think this is a win-win situation for everyone. if you don’t like something, you should let us know. we’re not a hundred thousand leagues removed from our users. if you want to use the language, you have every right to tell us what you think about it; how you find it; what you want. if you make a good case for it, I think it could be done. that’s just my opinion. but I think we have an opportunity to together as a C++ community put forth C++ in an otherwise hostile environment that for some unbelievable reason thinks C# or Java comes anywhere near being as good a language. I don’t understand it. It’s not a question of knocking those languages. They took so much from C++ — it’s not hard, after all the hard stuff was worked out, to go back and clean it up. sure. C++ is messy. it was real hard to do. it was getting done while we were using it. we didn’t know where it was going. Bjarne was implementing it, using it, it became the tool we all used to make our living. we wanted it to be the best possible language for programmers. at least I did. I don’t have a philosophy. I don’t make standards. I just program and write. and I do that best in C++. C# and Java mean nothing to me. Now I have my own language to use on .NET. That was my personal agenda in all this. I think you should check it out.

 

it was a great adventure. I find C++/CLI is something interesting again about C++ for me anyway. I’m not a fan of standards. I’ve never finally been involved in one. It’s making a language that interests me, not in clean-up and all that necessary stuff for real-world production. I don’t have the head for that.

 

so, I just wanted to make a personal statement. I have watched the team here for almost 3 years. I worked with them sometimes. I snarled at them sometimes. I was fed up with them once or twice. and yet they have produced something really wonderful in my opinion, and it is much better than I had dared imagine. I just love it. I can’t wait to program with it – I’d like to drop everything and just start. this is exactly what I have been waiting for. to have a language to program .net. we didn’t have one before.

 

C++/CLI is a entry visa nto what I call 3-dimensional programming. The CLR gives you the run-time as an entity to query, to modify, to almost in a sense be alive in. everything in a native program has to be done at compile-time. that is way too early for me to know exactly what needs to be done in many interesting environments. can’t I wait? I’m not that performance critical that I need the machine.

 

my first analogy was going to be between the traditional Disney animation and the Pixar CGI, but I think a better analogy is between an instinct and a decision. that is, an instinct is the trigger of a built-in behavior that is insulated from and unaffected by the environment. a decision considers the environment (context) and memory (past behavior) in order to choose a best action. this is what is missing from native static programming. it really can’t be smart enough for the kinds of problems we need to solve now in my estimate. I can’t prove that.

 

I gave a talk at Disney Feature Animation a few months ago about C++/CLI, and a friend of mine who I love dearly, asked me, what do I need that for? he is in charge of plug-in 3D tools for Maya, a modeling toolkit for computer graphics. And he is right. But we need it I believe as a community going forward. and in that sense, we have opened that doorway for the C++ programmer. The worst case scenario was that the price of admission to this world was to have to renounce C++ — I mean, mea culpa. we’re such savages – we worry about performance, we break the type system, we make use of the underlying machine, we don’t follow enough rules. we’re loose cannons. Can’t have loose cannons. I personally didn’t want to accept that as being a true statement.

 

But you cannot argue something like that. I can’t say, hypothetically, C++ can be as good a language under .NET as Java or C#. Nobody would hear that – they would just see Lippman being defensive, or delusional. you have to demonstrate it. That’s the only way to really convince people. That’s the only way I can ever convince myself in fact. So, that is what C++/CLI means to me.

 

I know Bjarne has his reservations and dislikes. Well, so do we all, if truth be told. But it’s still just so wonderful overall. who cares if it’s not perfect. I don’t – I haven’t gotten anything perfect, trust me. i don’t know if it is better than this or that or the next thing. but it’s really pretty good and i’m going to use it. and we really did it as a team.


Comments (26)

  1. Zach Zolton says:

    Mr. Lippman,

    I am a mid-twenties programmer working and doing grad school. I wasn’t there when you guys were deciding about C++, but in a way I wish I was! I love C++, but at my work I’m using .NET languages.

    I really like the uncluttered C# style, and the .NET Framework. I’ve also had to use VB.NET, which I think is an abomination. VB.NET tried to keep syntactically compatible with VB 6, while adding language "features" for .NET coding. They only created an verbose Frankenstein.

    I hope that doesn’t that doesn’t become analogous to CLI/C++. (I couldn’t even get into old Managed C++) There are a lot of great independent C++ libraries that are what help identify the C++ community (of which I’d like to be included).

    So, if at the end of this all, I can compile non-Microsoft C++ libraries, and use the .NET Framework – both with ease – I’ll declare CLI/C++ a winner… I’m waiting; I want to try and reserve my judgement.

    Best of Luck,

    Zach Z

  2. Fritz Onion says:

    Stan – I just want to know why you’re throwing me as an exception? What have I ever done to deserve this?? :) :)

    -Fritz

    PS – this post alone has convinced me to spend some serious quality time with this next release of managed C++

  3. stan lippman says:

    hi, fritz. gee, it’s nice to hear from you. i hope you are well :-) let us know what you think!

  4. Nish says:

    Stan

    I believe that there are limits to which C# (or VB) can go to implement every IL-supported feature in .NET. But since the nature of C++ allows it to be the thinnest wrapper possible over assembler (or IL in this case), it’d be wonderful if C++/CLI allows us to implement every IL-supported feature there is. That alone should entice native C++ coders into moving to C++/CLI rather than C#/VB for .NET programming.

  5. coops says:

    i would like to say im sooooo looking forward to checking out the new C++/CLI. Ive been following both you and herbs entries for some time and think your doing excellent work..

  6. RBischoff says:

    Hi Stan,

    First off I just want to thank you and your team at Microsoft for the hard work that has taking place on C++/CLI.

    I actually love C++, but I was doing all development in C#.NET and I didn’t particularly like the syntax of Managed C++. However, I am really excited about C++/CLI, it seems to now be a first class citizen in the .NET realm.

    C++/CLI (IMHO) is a very nice langauge to program .NET, and it will offer the developer power/control with .NET coding. I will be doing all my .NET coding in C++/CLI instead of C#.

    Oh yeah, C++/CLI is also a great langauge for unmanaged code, and the best langauge for mixing <un>managed code.

    Thanks again to the C++/CLI team.

  7. Ben Chan says:

    I used to be a win32 C++ programmer and a big C++ fans.However, no matter how much I love C++,the STL and templates.It cannot beat the productively of C# and java in high level application development.

    I have no idea why other ppl is so hostile in C++/CLI.The native C++ sucks, I hate long compliation and linking time. I hate the pre-compiled header stuff and tons of complicated compiler settings.I hate I have to maintain both .h and .ccp file.I hate my template code is not 100% portable to other compiler.I suffered enough.

    I love programming and also love to become a productive developer.I don’t care about the standard stuff, I don’t give a dxxn it is MS/SUN who design the next generation of C++.As long as it is good,I’ll use it.

    If C++ not getting upgrade, I bet I won’t have any chance to use C++ forever.I love C++ and I don’t want to see it die slowly.I hate hearing ppl keep attacking C++/CLI without doing any constructive suggestion.Some of the ppl fight against it because C++/CLI is build by MS, some are simply religion matters.

    For whatever reason, I just feel sad about those irrational ppl and I think the current C++/CLI’s implementation is cool as hell.For me,Stan lippman and his team is saviour to C++ and I would love to say thanks to you and your team’s effort.C++/CLI is the only MS product I’ll go for.

  8. Glen says:

    Stan

    I have long hated Microsoft for turning the endless possibilities of C++ programming, into the endless monotony of unproductive error prone COM programming (and poor design objectives), that Windows development had grown to typify. Microsoft I charge you with no less than nearly killing the Windows C++ community that you created.

    But that was yesterday! I am truly astounded and excited that that you and the C++ team have finally heard our call, and have taken up the enormous challenge of returning our great language back to us. The new C++ 2005 appears to be all that I have been hoping for. Though I use C# now and have a lot of respect for it, I relish the chance to ditch it! If C++ can return to being the language of endless possibilities, then I can’t wait to get back to using it on the world’s most popular programming platform.

    You and your team appear to be doing a fantastic and thorough job. Keep up the good work.

  9. Kate Gregory says:

    I have been spending the last new months showing C++/CLI to people wherever and whenever I can, and I keep hearing exclamations of delight, followed by "I’m switching." Sometimes it’s back from C#, sometimes it’s they’re finally leaving MFC, whatever. Their hearts were with C++ but they couldn’t use it, and now they feel a sense of freedom and relief that they can again. I really like being the bearer of this news. Thanks to Stan, Herb, and the rest of the team for creating the news for me to bear.

  10. I thought the decorated string literals used in MC++ made perfect sense. If you were expecting a String^ you should use S"fritz", and if you are expecting a const wchar *, you should use L"fritz". It doesn’t seem like much to ask, that people specify what kind of string it is in places where it would be ambigious.

    I really like what has been done with the new C++/CLI stuff, but just like in MC++, I would expect any C++ code to do the same thing wheather it was compiled for win32 or for CLR.

  11. Mark Mullin says:

    Geez, Stan – I’ve got to read your blog more often so I don’t just post complaints on it. But here goes….

    I can see the reason for C++/CLI as a waypoint for legacy code, and I can certainly see a limited implementation of C++ if you just want the familiar C++ syntax (that said. C# is not exactly off on another planet). And I can see mixed code, and all the other things you’ve talked about.

    What I can’t see, in fact what I think is dangerous, is to make C++/CLI try and ‘act’ too much like a C++ native. What I mean by this is illustrated by the example you give. While I also wouldn’t (errr, shouldn’t :-) ) throw numbers and strings as exceptions, I don’t believe that the CLI should bypass it’s own native types when effectively throwing one of it’s own native types.

    Specifically, in this example I’d argue that the developers you refer to recognize the interplay between CLI and native and do something real fun, along the lines of MI – try and throw to the CLI string^ catchers – not caught ? then try the const char *. Admittedly, this is a can of worms when you start looking at a series of nested catchers, but we sorta figured that out for multiple inheritence, and this problem is roughly similar, specifically — whether this search resolves breadth or depth wise (search local exception catchers for any acceptable type or search hierarchy for best acceptable type

    In any case, I think that there are going to be two modes of C++ use given the success of this project – people like your friend and myself burn millions upon millions of machine cycles. .net is fast, John Carmack proved that beyond a shadow of a doubt, but 85% of realtime ain’t realtime. At other times, yeah it’s nice to have a ‘safer’ environment, although I personally lean towards a real OO language in that case (Smalltalk :-)) BUT THE TWO ARE NOT SYNONYMOUS, and trying to make them so is a receipe for disaster! In short, C++/CLI should propagate towards C++ native, it should not do things as in your exception example, because this looses the most vital distinction of all – am I managed code for managed problems, or am I some performance or bust hairball. There’s three areas here, (native, managed, and moving between the two) and it’s that last one that needs to be recognized as a real situation, not something to be swept under the covers. If my managed code threw a string, then I think that implies I prefer a string^ over a const char*, but that I also expect a const char* to catch if there is no ‘earlier’ valid string^ catch

    Anyway, my 2c. Keep fighting the good fight, happy holidays, etc

  12. Herb Sutter says:

    Thanks, Mark.

    >>There’s three areas here, (native, managed, and moving between the two) and it’s that last one that needs to be recognized as a real situation, not something to be swept under the covers.<<

    Sure. I hope that we do that.

    To recap, we convert a string literal to String^ implicitly in those cases where we can be sure it’s the right thing to do, usually because we know the immediate target, and throw “literal” isn’t such a case.

    You then requested:

    >>If my managed code threw a string, then I think that implies I prefer a string^ over a const char*, but that I also expect a const char* to catch if there is no ‘earlier’ valid string^ catch<<

    It sounds like you want to additionally make catch clauses for either String^ or const char* implicitly be able to catch an exception of either type. This seems pretty subtle, likely problematic, and probably unwise.

    Example off the top of my head: Say f1 calls f2 calls f3 which throws “literal” – if f2 catches String^ only and f1 catches const char*, do you really want f2 catching the “literal” as a String^ instead of letting f1 catch it as its exact type? And what if f1 and f3 already exist and are working, and then someone later writes f2?

    I am uncomfortable with that path because it would explicitly blur the distinction between two distinct types. That’s a very different scenario from the convenience scenario we are supporting with the “literal”-to-String^ convenience conversion which basically knows the right type and saves you writing a cast.

    Fortunately, we’re talking about how we support a construct that programmers shouldn’t be writing in the first place. :-)

    Thanks,

    Herb

  13. Mark Mullin says:

    Thanks for the response Herb (& Stan, implicitly)

    I agree with your point, that’s why I alluded to it being like MI – then again, it’s that relation that makes this ‘interesting’ :-)

    I agree you’ve been bad if you do this particular example in the first place, but, then again, I’ve been bad before and will certainly be again.

    But……… C++/ILM is going to exist in a world of nice managed types, and most likely not so nice unmanaged types. No big deal, IntPtr is already my special friend in C#. But^2 – I know whenever I look at my C# code and see IntPtr, I’m looking at something nasty from the outside. I can easily write C# code that deals with things coming across the p/invoke boundary and from within the managed app without standing on my head to figure out what’s what.

    I think, because of the greater overlap between C++/ILM and C++/native, it might be worth considering the ‘network’ of type relations – A string^ is a const char* is a char* is a void*…. being just one example of the trip from the warm safe womb of managed code to the raw metal of the machine.

    It’s been a long time since I’ve been involved in language law, but I think there’s an issue here which is a product of the fact that C++ will have two very distinct operating environments after you are done, and that there is an excellent chance those environments will be mixed in a single program, via p/invoke at the very least. I think there’s a good case for amping up type conversion operations, and I think that Stan’s original example showed that.

    As a concrete example, consider this. F1 is a high level control function, and calls two functions – F2M (managed) and F2U (unmanaged). F2M throws a string^ and returns a string^, F2U throws a char* and returns a char* (yeah, I’d use stl).

    Now assume that F1 implements Process(string^ myData) and Process(char* myData)

    Now consider

    try {

    f1.Process(virtualInF2(myData))

    }

    catch(???)

    If I’ve got a clearly defined pattern of type propagation (yes, I admit what I’m asking for would actually be a real bear, but anything worth having……) then I’ve got a world where like goes to like, or follows clear rules of conversion. In the case above, given you could solve tbe ?multiple type/MI? issue, I’d have a much more powerful system. This would be far more powerful than just shoehorning C++ into .net, it would be C++ that could allow developers to stand simulataneously (and as safely as possible) in managed and native worlds at once.

    I don’t deny this is difficult (that’s why I said network and not dag) – I also believe you folk have something truly new under the sun here, and I think you need to recognize it’s needs. I don’t like the idea of just tossing the managed sides typing information and racing for the lowest common denominator in C++. After all, if I wanted that, I’d sed all my types to void* and use native :-)

    Regards

    MMM

  14. Jason Li says:

    I like the current string literal’s design. It is reasonable & convenient. And I think if there is a amphibolous statement like the following:

    throw "fritz";

    it is OK for C++/CLI compiler to just give an error/warning info, since there is no context to decide the type of "fritz". The programmers are responsible for changing it to a clear statement like the following:

    throw (String^)"abc";

    And the analogy of instinct vs. a decision is very wonderful.

    As for those who are unhappy with C++/CLI, I think the problem is Microsoft, not C++/CLI itself. If C++/CLI can only be used on Microsoft platform in future, it will be rebuked by people continuously & emotionally.

    If Microsoft has an open mind on CLI, let more organizations & companies involved in CLI’s development, C++/CLI will gain great success. As a CLI language, C++/CLI has already succeeded. But C++/CLI’s popularity is dependent on CLI’s popularity, C++/CLI’s final success is dependent on CLI’s success.

    Yes, Microsoft has submitted CLI as ISO standard, but that’s not enough. After all, the current fact is that only Microsoft has implemented an industry-level CLI (Mono is too young.)

    To tell the truth, C++/CLI’s design is already good enough, and the current C++ team is the most respected & excellent team in Microsoft’s history. By the way, in China, many programmers tell me that they love C++/CLI, they will come back to C++/CLI after having given C++ up for several years.

    Thanks for you & your team’s great work!

  15. stan lippman says:

    i don’t see how you can generalize like this on such a fringe inconsequential oddity. however, i appreciate your taking the time to articulate your position. i hope we’ve given it full consideration. that’s all we can do in a debate like this. thank you.

    that said, (a) i still stand by my initial evaluation in my post, and (b) i am closing

    off this thread. no further comments on it

    will appear.

    thanks to mark and herb for engaging in a thoughtful debate. everyone’s positions should be clear at this point.

    have a good holiday … i will see everyone next year.

  16. objectref says:

    I don’t see the usefulness of "C# mean nothing to me"…

    C# is .net oriented at the first place and in my opinion, a beautifully designed language.

    So, all the work your team has done, although very good but still it will try to accomplish the right way something that C# was designed to accomplish 4 years ago, and it surelly has succeeded on it.

    I also do not see, if .net is the future, why someone will dump C# and go back to C++.

    And don’t tell me about the somewhat less instruction set that C++ compliler will produce over the C# compiler because, alas, we live in 3GHz processors, and productivity is in demand nowadays…

    I now C++ is your favorite one, but as i see the evolving of other languages, i think that they put C++ on the corner, release by release…

  17. anothr user says:

    One new subscriber from Anothr Alerts

  18. In the last entry, I celebrated what I felt was an elegant solution to the problem of the string literal in the context of overload function resolution. But it turns out there is another area in which the string literal proves problematic. Who would hav