Loading User Information from Channel 9
Something went wrong getting user information from Channel 9
Loading User Information from MSDN
Something went wrong getting user information from MSDN
Loading Visual Studio Achievements
Something went wrong getting the Visual Studio Achievements
Herb Sutter: (Not Your Father’s) C++
Apr 13, 2012 at 8:57 AM@C64: The big thing I personally got out of last week's event and chats was that Standard C++ now does have a safe subset, but we need a concrete description -- ideally a mode. It has made me think again about doing a scrub of all standard C++ language and library features and marking some as "unsafe" in some way (possibly that allows overloading, such as for vector::op[] overloads for safe and unsafe instead of the current hack of providing op[] and at() which almost nobody uses), then supporting a switch that enables only safe mode. I believe I know how to do that very efficiently now that we have C++11.
I'll have to look into this more over the summer. I think saying "use this (possibly standardized) switch/mode and your modern C++ code is type- and memory-safe" would be a big deal and an important missing piece to completely answer and dispel this question. The question "what subset of C++ is that exactly and is it a usable subset" is a legitimate question now, and IMO wants a more concrete answer than we have today. I did look at this about four years ago, but
we know more now, and (b) C++11 has already added most of the then-missing pieces now.
GoingNative 3: The C++/CX Episode with Marian Luparu
Nov 15, 2011 at 11:43 AM@Mort: "Interesting, as Herb Sutter explains, the direction received by his team from management was: R1. Enable full power and control, including both consumption and authoring. R2. Be as simple and elegant as possible for the developer. Right from the outset, we see that there was no requirement to conform to the language standard."
Because that's so obvious it goes without saying. As I continued (and you then quoted) a key goal of our management and my design team was, and the boldface is in the original: "Minimize the actual amount of non-portable non-ISO C++ code/tools developers have to write/use to use WinRT." You can call it failed, that's your prerogative, but it's disingenuous above to declare that I said we didn't have it as a goal -- it was one of the three I boldfaced.
Here's a clear counterexample: Look at C++ AMP. The same management and same design team in the same product cycle did a complete extension of C++ for GPGPU programming as almost a pure C++ library that follows C++ STL conventions faithfully and relies on C++11 features like lambdas -- with only a single language extension because one was necessary. We'd have been happy to do it without any language extensions, but that's not possible because current GPUs cannot handle the entire C++ language -- nevertheless, even with some extensions necessary, we're very proud of having been able to find a single general extension that enabled the rest of it to be written as a library.
There is not another GPGPU product for C++ out there in the marketplace today that does it with as few language extensions to ISO C++ as we did in C++ AMP in this same product cycle -- just one extension, the rest as a pure library. If you want to draw any conclusions from that, it would be fair to say that in the GPGPU space Microsoft values C++ more than any other company (all others primarily target C99 dialects, with at best C++ wrapper libraries) and placed higher priority on ISO C++ compatibility and minimizing language extensions than any other major GPGU vendor (they all have way more language extensions).
GoingNative 3: The C++/CX Episode with Marian Luparu
Nov 15, 2011 at 11:26 AMI asked:
"consider:
ref class Screen {
public:
int DrawLine( Point x, Point y );
};
...
What is the minimal code syntax and build steps it would it take to express this in a MIDL-style approach, and across how many source/intermediate files? What's the best we could do in that kind of alternative approach?"
@PFYB answered: "For the sake of completeness:
// ISO C++
class Screen {
public:
int DrawLine( Point x, Point y );
};"
If that's your answer, you didn't understand the question.
Let me try to explain, at least with a few basic examples, why I don't think the above begins to answer the question because there's just not enough information:
You also didn't answer "what... build steps it would take" -- what are the build steps and tools involved, in what order are they invoked, and what does each one do? Also, "and across how many source/intermediate files" -- I think your answer to the source is no more source files, but what about intermediate files?
I'm just trying to explain why the above doesn't begin to answer my question. To me this isn't an alternative design, it's writing plain C++ code and waving "do the right thing to make it work" hands.
GoingNative 3: The C++/CX Episode with Marian Luparu
Nov 15, 2011 at 11:06 AMI asked: "Before I go further, let me sanity-check something: Do we agree that the route of "extending TLB #import" leads to a full ATL + MIDL like approach?"
@PFYB answered: "No."
Then you're clearly mistaken. WinRT is COM (and then some), and in general you can't author COM types without all the additional information about the types you can specify in an IDL file -- whether those information-carrying extensions go into a separate IDL file (the MIDL approach) or into the main .cpp file (the C++/CX approach, though it could be done with different syntax, but it must necessarily be just as rich in order to to the job).
@PFYB: "ATL + MIDL is a reasonable way to write code, but we are talking about something else. We are talking about not only "extending TLB #import" to cover WinRT modules, but also about doing the reverse of #import, that is, parsing regular C++ code ..."
Again, "regular C++ code" doesn't carry sufficient information.
@PFYB: "...and generating wrapper C++ code in order to expose regular code to WinRT.
Here is an example:
// ISO C++
struct I1 : public IInspectable {
virtual void F() = 0;
virtual std::wstring G(int) = 0;
};
struct I2 : public I1 {
virtual winrt_ptr<I1> H() = 0;
};
class C : public I2 {
public:
C();
...
};"
Short answer: There's not enough information in that code. Also, this doesn't avoid the need to generate wrappers, you will be generating wrappers anyway such as to change the std::wstring type to HSTRING and change all the function signatures to HRESULT returns and generate code to catch exceptions and translate them to HRESULTs and a dozen more things (I think you know this, but others on this thread think wrappers are unnecessary so I'm noting this for completeness; wrappers are necessary, and the goal above would be to generate the wrappers automatically from the above code).
To take just the first line, a few problems I can see are:
Similarly, in the other two cases with the pattern "class X : public Y":
So where exactly is the syntax that lets the user state whether X is intended to be a class or an interface? what its default interface is? whether to actually inherit and do pointer conversions under the covers or emit a requires relationship into metadata and QI all the time? whether to aggregate the FTM (free threaded marshaler)? and a dozen more things like that.
Disclaimer: This is just scratching the surface. It is not by any means a complete list.
By the way, as I mentioned last night, I tried exactly this approach early in the C++/CLI effort -- there, ": public IInspectable" was spelled ": System::Object". Quoting myself: "For example, I asked "why do we need a new class category, why doesn't it just work to have 'class X : System::Object' be an inheritance tag from a magic type that the compiler can treat specially?" and spent several weeks trying to make it work, and several dozen similar questions -- many similar to questions in this thread."
@PFYB: "I hope the above is sufficiently clear."
I do understand what you want. I was in the same place in 2004 and tried many variations on this theme, and then we tried it again in 2010-11 in case WinRT might have removed enough of the constraints we had with .NET so as to make it possible (it didn't).
I think it's clear that we aren't going to be successful designing this together in a comment thread, and if you refuse to accept that it isn't that simple, from the people who tried and understand the requirements and constraints deeply, then the only alternative is for you to invest the time to make the technical effort yourself -- not just sketch things that look plausible, but build the prototype (including correct and complete binding to WinRT features and high-quality VS product tooling integration) and demonstrate a proof of concept.
This isn't science, it's engineering. There are many plausible ideas, but the only proof that an idea works is to show working code. As you do the exercise, you will discover a number of constraints and problems.
But sometimes the only way to explore is to go into the wilderness in person to see for oneself, if one won't accept maps from people who've been before. And that person on his own trek may indeed find something new that the earlier explorers overlooked -- that's how we make progress -- but one won't know until he actually goes, one can't decide that by the Victorian method of making a pencil-and-paper sketch sitting in the living room armchair by the fireplace.
GoingNative 3: The C++/CX Episode with Marian Luparu
Nov 15, 2011 at 12:21 AM@Glen: "Hurrahh that some smart people went to lengths to avoid using simple keywords; but it "befounds" the rest of us average joes that anyone would have ever have wasted time proposing or considering attributes for those roles in the first place, even given the sheer fugly factor alone!!"
Forgive me, but this is a perfect example: "I can't imagine why it was so hard to get ISO C++ to not use simple keywords virtual override/final" is a perfect parallel to the questions about "I can't imagine why it should be so hard to surface WinRT in ISO C++" -- you have to know the many social and technical constraints on the problem to see why things that everyone initially believes ought to be easy (or easier) really aren't.
The short answer in this case is that:
I personally led the charge on this one, at multiple meetings. If I hadn't done that, today we would have a C++11 with [[override]] and [[virtual]] -- not only in that hideous style, but in weird grammar positions. That's what was the default solution already voted into the draft standard, and what we would ship with unless there was consensus to switch to some other specific alternative (which is a very high bar).
@Glen: "Not to sound ungrateful though, the reality of the man on the street is this: as long as the WG21 team can agree, that the concepts keywords are serving are useful - which should have been relatively easy since Java et al had already proved the ones we were talking about (i.e. nullptr, override, etc., which was my point) - the rest of us mere mortals would have accepted even full keywords in this context and dealt with the consequences! I don't mean to downplay your invention of a super keyword but to say anything other elides these facts."
That's simply not true or realistic. There are billions and billions of lines of working C++ code in the world. Breaking even 0.1% of the code in the world is a major breaking change that would directly hurt adoption of the new standard. Compatibility is king for C++ -- it always has been, because if C++ had not been essentially 100% C-compatible, essentially a strict superset of C, it would never have been widely used outside of AT&T. Even now C++ faces great pressure to remain a nearly perfectly compatible superset of C, to the point where WG21 felt obliged to formally add C99's preprocessor extensions and the entire C99 standard library to C++11.
@Glen: "That microsoft firmed up an implementation of some of those ideas, I am willing to accept, but your comments tend to suggest that the majority of invention came from C++/CLI and now that C++/CLI was required to proove them for the cases we were talking about. I think you will find the mainstream view is that the core ideas were not new (as you agree) but also that Java piloted those features sufficiently to see the value of them and that it elides a lot of reality to credit C++/CLI with the origin of those features, so you shouldn't do it. Still, like I said it's a minor point, we can agree to disagree. I still appreciate the work done on it."
The point wasn't the feature, it was the difficult legwork of how to expose the feature specifically in C++, and specifically with perfect backward compatibility with existing C++ code. The answers were not obvious.
@Glen: "I take your point about fusing C++/CX and WinRT. But never the less, their existance is fused. I don't see that one exists without the other? ref class has no future without WinRT?"
Not only does it have a future, but "ref class" already had a past even before C++/CX and WinRT in C++/CLI and .NET -- it has now successfully bound to two very different (if related) object models, namely .NET and WinRT. And we have enough experience now to be pretty sure if we need to ever bind to a new static OO object model, we can reuse the same language extensions with a new switch to signify the new target (just as today with /clr they target .NET, and with /ZW they target WinRT), not invent something new. (However, I don't know yet if they would be sufficient to bind to a dynamic type system's object model, which is both similar and different.)
GoingNative 3: The C++/CX Episode with Marian Luparu
Nov 14, 2011 at 10:46 PM@Glen wrote: "If the problem can't be solved in a transparent way, either the platform model is too complicated or it will harm C++."
I get it -- you want it to be true that ISO C++'s great flexibility is so powerful that it's sufficient to directly express all object models. It's frustrating to be told by people who it seems ought to know better that it isn't that way. I understand; I wish it were true, too.
You may not realize how much I understand your frustration.
Let me tell you story.
In the Way-Back Machine
In December 2003, an effort to revise the Managed Extensions to C++ was already underway (an effort that would later be called C++/CLI), but I was not participating in it at the time and in fact had heard little about it. I had joined Microsoft just the year before and was still figuring out the huge company and its platforms. I already had a lot of C++ experience and love, as did the other people on the team, but was still drinking from the fire hose of information and trying to absorb as fast as I could all the deep details of the platform and tools that people around me already knew.
That December, the C++/CLI effort had hit a technical and organizational roadblock, and people started coming to me to look for help. In the end I asked for, and was given, the job of leading the design team. As you can imagine, this always presents tensions and challenges for a project team already in midstream, and especially when the newcomer has some pretty hard-nosed design sensibilities about doing things the ISO C++ way.
For the first several months I made a real pain of myself, insisting on understanding the deep rationale for every single feature because I just couldn't believe such a set of language extensions was needed. For example, I asked "why do we need a new class category, why doesn't it just work to have 'class X : System::Object' be an inheritance tag from a magic type that the compiler can treat specially?" and spent several weeks trying to make it work, and several dozen similar questions -- many similar to questions in this thread. And my probing was most of the time not specifically whether a language extension was needed; the questions were deeper, to find the goals and constraints -- 'what semantics need to be achieved?', 'what does the code generation have to be?', 'what is the IL we have to map to and round-trip with?', 'how does the compacting garbage collector work?', 'why can't regular pointers point into the GC heap?', 'what are the exact semantics of pinning an object's memory?', and so forth.
In the end, once I grokked the main design constraints, I like to think that I did make a number of contributions that improved and simplified the design quite a lot. But at first I was really wishing it could be 'just ISO C++,' and it was painful when I really began to understand the deep reasons why wishing wouldn't make it so.
Over the course of those first several months, I gradually realized that a few patterns were emerging in my thinking, notably (but not only): 1. I kept trying to make a language feature look like a library, but it still required compiler knowledge and so it was still a language feature in library-syntax clothing and I was only fooling myself that that somehow made it more like a library. 2. I kept discovering differences where this really was a foreign object model that couldn't be expressed directly in ISO C++ any more than full ISO C++ classes with virtual functions could be expressed directly in ISO C.
I see the same patterns here in this thread, and I understand completely because I said the same kinds of things for months in early 2004 during the C++/CLI design effort when I didn't understand the full problem. I appreciate the patience the team had with me as I absorbed it, but even then it took months in daily meetings in rooms with whiteboards and high-bandwidth interaction.
In this comment format, I can't possibly convey all that learning derived from months of face-to-face interaction with the best experts on the technologies, but maybe I can distill some key learnings and why I felt they were so important in changing my understanding of the nature of the problem.
Pursuing an Analogy: A General Answer to "Why Language Extensions"
Let me pursue the analogy with expressing virtual functions in ISO C, because it's a very good one that directly applies to expressing foreign object models in ISO C++.
In the past, people could have (and sometimes did) argue at great length that C is enough (heck, it's Turing-complete and you can write OSes in it) so "you don't need C++ classes and 'virtual' etc. added to the C language, you can write your own vtables in C" and look here are three projects I can cite that did that...
... Yes, clearly, you can. But that "you can" completely glosses over the costs, including the usability and other drawbacks of doing it by hand, including the quantity of code you write, the quality of the code you write, the quality of error messages, the run-time performance, and the tooling difficulty and quality. If that list sounds familiar because I've mentioned those same things already earlier in the thread, it's because it's what always happens when you fail to expose high-level abstractions and instead use low-level abstractions plus coding conventions.
So how would you answer someone who presses you with the question, "well, can you tell us why it isn't possible to just write our own vtables in C"? Of course it's possible -- and at this point, before you can say more, they may tend to interrupt with 'ha! it's possible, you admit it! so you can have no valid reason not to have done it in just ISO C' -- ; but that doesn't change the fact that it's not a good solution because you're missing abstractions that belong in the language because they require compiler knowledge.
Key point: As soon as something requires compiler knowledge, it's a language feature. Pushing the language extensions somewhere else, like to a MIDL language+tool, is just squeezing the toothpaste tube and moving the extension to somewhere else in the design space; it's not removing the need for language extensions.
Corollary: Magic libraries and compiler code generation tools are language extensions. As soon as something requires compiler knowledge, it's not a normal library type, and wishing won't make it so. Neither will giving it a library-like syntax.
Note that the answer to nearly all questions of the form "why did you need a language extension for X" is "because X required compiler knowledge." The reason I say "nearly all" is:
Limitations of the World's Most Flexible Object Model
Finally, the thing that was perhaps hardest to accept was that this beautifully flexible ISO C++ object model that seemed like it could express anything, this so wonderfully controllable and flexible and efficient object model, could not after all directly express all interesting object models. Some object models would stay foreign (at least until added to some future ISO C++) -- not just dynamically typed object models, but even statically typed object models that have different rules and constraints. So the realization was the following:
Key point: There are interesting object models that are not directly expressible in C++. "Directly" means in the language without relying deeply on convention and discipline; you can express anything in assembler via convention and discipline, but that observation is neither helpful nor interesting. "Other object models" mean ones that reflect different object layout assumptions (e.g., hiding data rather than exposing it the way the C++ object model assumes and requires), different static and dynamic restrictions, and even different language rules (e.g., deep virtual dispatch in constructors). When you need to bind to them, and you want to do it well with best quality and performance and toolability, you need language extensions.
Corollary: Using those object models well from C++ requires a language-level binding. It can be done without a language binding to the same degree as virtual calls can be done using hand-coded vtables in C.
Let's return one more time to virtual functions expressed in ISO C.
Consider what would happen if you really tried hard to do virtual functions in C without language extensions. You could imagine creating a wonderful set of C macros (just like #import-enhancing macros) that automates a lot of the repetitive coding for you, and the resulting code may even look reasonably nice. (After all, when we're in this "imagine if" mode before doing real detailed systems prototyping things always look rosier and feasible because you haven't found the problems and limits yet; but let's assume what I just described was actually possible in this case for C macros simulating virtual functions.) (And I said "you could imagine creating" on purpose -- that's what this thread is often doing.)
Here's what we know you will never get without a language feature:
That's what (well-designed) language abstractions always give you over coding convention + discipline: More concise, more elegant code. More robust code. Higher quality error messages. More performance optimization opportunities. Better toolability. This is not wishful idealism; it's inherently true, every time.
All of these things -- said above about language extensions to C for dealing with virtual functions -- apply to language extensions for binding C++ to foreign object models, for they are simply always true for all language extensions that eliminate conventions + discipline.
ISO C just isn't suited to natively doing OO programming with virtual functions, any more than ISO C++ is suited to doing a component object model with true encapsulation and ABI safety. ISO C and C++ are both incredibly useful, powerful, and flexible languages; but an important part of using a power tool is to understand its limits. Sometimes that takes time and deep experience at the boundaries.
@Glen wrote: "How many other languages are you going to extend or recommend get two notions of class?"
Let me ask you a counter-question, please.
What would you say if you were proposing virtual functions for C, and someone asked, "Why do you recommend getting two notions of functions? Functions are functions, darn it, everyone knows that, virtual functions are just functions and I'm sure you can express them in ISO C without extensions, we have function pointers and everything you need."
Two questions:
It took me a while to get all this through my head, so I know it takes time.
I don't know if this will help, but maybe it will.
GoingNative 3: The C++/CX Episode with Marian Luparu
Nov 14, 2011 at 4:05 PM@Glen:
Re: "I believe the extensions you attribute to being "thanks to C++/CLI" are really more "thanks to Java" or someone prior to C++/CLI. I am surprised you keep stating this claim, I know you helped push them through to C++ but that's different from originating the basic concepts."
Of course many languages, including before Java, had some of these concepts (spelled in C++/CLI and C++11 as nullptr, enum class, override and sealed/final). But ISO C++11 had many alternatives for each one (choice of keyword, grammar position, attribute or not, etc.), and standardized exactly C++/CLI's syntax and semantics with few or no tweaks. The C++11 keyword "nullptr" and the "enum class" syntax and semantics are C++/CLI. For the other two it's even clearer: "override" et al. are ISO C++'s very first ever contextual keywords; there were many other options, from attributes to fully reserved words, and C++11 followed directly the trail blazed by C++/CLI to make them contextual even though that was a major novelty for C++11, but because it had been shown to be a great option that works seamlessly in practice based on the field experience with C++/CLI it was considered safe for standardization. I consider that a big win for the whole C++ community, because it would have been beyond awful to have override and final be [[override]] and [[final]] attribute, or based_check_override and base_check_final deliberately-uglified-to-not-break-existing-code keywords, which were the other major options n the table.
You really don't get field experience with future-standard language features unless someone implements them as an extension, and so C++/CLI / C++/CX has turned out to be a sort of "Boost for language features" and I expect more features to be proposed for ISO C++.
Re: "Regarding properties, events and delegates, if they were of value to ISO, it's stunning that they aren't already in the language or weren't more widely debated this time around and more stunning why MS didn't at least propose them so either could happen or advance their definitions further - you already had all the experience you needed with them in C++/CLI and they feature again in C++/CX unchanged."
Good question, two reasons (caveat: I'm going from memory here, which can be dangerous):
Re: "Regarding goals B1, and B2."
I'm not clear from your answer which you prefer, B1 or B2?
Re: "C++/CX as it stands requires me to wrap all of my libraries - my classes, i.e. the ones that *I* produce; at the class level"
C++/CX doesn't do that, WinRT does. How is this different from COM or CORBA?
ISO C++11 doesn't have ABI-safe components or modules; it can't express those. That's not surprising, because the design requirements for C++ classes and ABI-safe classes are inherently different and incompatible:
So to have ABI-safe component types inherently requires non-ISO C++ code somewhere.[*] The only question I can see on this thread is where to put that non-ISO C++ -- and putting it in a separate MIDL file with its own language extensions and compiler is no less of an extension and no more portable than putting the extensions in the same source file.
Re: "Unlike, say, a Win32 GUI API, that you wrap, C++/CX wraps you, at the class level"
(Again, this should say WinRT.)
Right, like COM and CORBA and the .NET CLR, WinRT is a runtime environment with its own object model, not just a library. The task my team was given was how to enable C++ programmers to consume and author types in that universe with as minimal impact to C++ code as possible by minimizing the amount of code/tools that programmers would have to write/use to work with the extensions.
Re: "If Bjarne really thinks this is a good idea"
Just to be clear, I was not claiming any of those participants endorse C++/CLI, I was saying that they actively invested effort to contribute to the design of C++/CLI to make it the best quality it could be and as compatible and conflict-free with ISO C++ as possible. Bjarne prefers no extensions at all whenever possible, and wishes we needed to do fewer, while recognizing that extensions are necessary to deal with different operating environments (such as in this case).
Re: "Whatever the means, wrapping is what makes C++/CX not viable in of itself IMO. Anything that doesn't virtually completely remove the burden of wrapping your own classes (even if you could justify the need to do it to start with, which I am not yet sold on either), is wrong; because it harms C++ productivity no matter how you do it - unless you don't do it. That's my stance, don't do it. If the problem can't be solved in a transparent way, either the platform model is too complicated or it will harm C++."
See above, the fundamental difference, starting from basic requirements, between C++ types and ABI-safe component types.
How can you expose an API surface to any of WinRT, COM, CORBA, or .NET CLR without using their types? The question isn't whether wrapping is necessary; it is. (If it weren't, then generations of COM and CORBA vendors have been somehow naive.) The question is only how to spell the extensions and where to put them.
Herb
GoingNative 3: The C++/CX Episode with Marian Luparu
Nov 14, 2011 at 10:09 AMInteresting; I'm glad to see how well that interview has held up over the course of a decade where my own understanding of Microsoft products/platform/ecosystem, as well as the course of the industry through through a major transformation or two, has changed a lot. I still agree with pretty much everything I said, including the need for further conformance to the new C++ standard now that it has stabilized and was published last month.
@PFYB asked:
Taking them one at a time:
1. It's not a brand-new set of extensions, rather it's essentially the same as C++/CLI. This was deliberate; once we realized were were on a path of doing language extensions again for the reasons I tried again to clarify in my note a minute ago, I did not want to create yet another different set of extensions. (There were several attempts from other people and teams within Microsoft to propose other extensions including many variants of the @ character, and despite considerable pressure to do that we steered away from the shoals of inventing yet another thing where you'd see code like @IFoo everywhere. There were so many that by the end of last year "hey, why don't we just use @ here" had become a running joke within our design team, because it had been proposed by so many people using so many different potential syntaxes for such a long time.)
2. We think so, given the constraints I tried again to describe in my last comment. I haven't given up trying to find and answer the question here.
Referring to that comment, it comes down to whether design requirement R2 is important to you, and whether you prefer choice B1 vs. B2 which are different ways to advocate for ISO C++ purity and minimize impurity.
3. Yes, because C++/CX is C++/CLI (modulo spelling gcnew as ref new, and very minor differences such as when WinRT doesn't support one or two things that .NET does, like generic classes). C++/CLI is the only set of non-ISO C++ language extensions in the world that was developed openly in an international standardization process with the participation of a who's-who of the participants and officers of ISO C++ (WG21), including Bjarne, IBM, Intel, EDG, Dinkumware, Plum Hall, and others including notably experts from UK and France, whose contributions were very helpful and changed C++/CLI to make it better than it would otherwise have been. This involved holding design and standardization meetings around the world, co-located with WG21, over the course of two years, plus telecons, sharing all documents openly (a first for Ecma), and other open engagement. C++/CLI is now an international standard (Ecma-372) that anyone can freely implement; that's a good thing now, because I've already heard about other compiler vendors investigating implementing C++/CX, which to my knowledge nobody ever did for C++/CLI.
4. Partly.
5. Yes, see above; parts of it have already been adopted in ISO C++11, and if the door opens for another round of language extensions then among the first to be submitted are likely to be things like properties/delegates/events which didn't make C++0x's priority list last time partly for lack of time and desire for more field experience with library vs. language approaches (which C++/CLI / C++/CX is helping to generate), but have always been of interest (see again Bjarne's 2004 wishlist).
6. Yes. Just like with C++ AMP, which we also announced earlier this year as a VC11 feature; I know of multiple investigations/implementations in progress for non-Windows platforms, and we are actively helping those implementers with their implementations. This is a definite change from the past; our viewpoint is that anything we ship, including library interfaces (not necessarily the Windows-specific implementations), should be something that we'd be willing to encourage other implementations and to submit to standardization if there's interest. That's one reason many of our new libraries in VC++2010 and VC++11, like PPL and AMP, are using c_style_naming (the naming convention preferred by ISO C++ and Boost) except where we were specifically binding to something that already had a different strong naming convention (e.g., the Platform:: namespace VC++-specific WinRT wrappers we provide we chose to PascalCase for consistency since they were specific to WinRT).
GoingNative 3: The C++/CX Episode with Marian Luparu
Nov 14, 2011 at 9:12 AMI've been thinking about this over the weekend. (Yes, I did read parts the thread last week and since then, though it really is too long to read in detail.) When two people express themselves and try to listen, and both still feel unheard, it's usually because of a fundamental disconnect. In this case, I suspect it's a difference about design goals.
Before I go further, let me sanity-check something: Do we agree that the route of "extending TLB #import" leads to a full ATL + MIDL like approach?
This seems to be a key point since early in the thread:
Later, when I replied saying in part that this path leads to growing a full MIDL language/compiler and toolchain model" (which we completely agree is feasible; we've done it in the past), two of the responses were:
So I'll assume (please correct me if I'm wrong) that we agree that extending the #import model for the consumption side means that the authoring side would employ something like a MIDL language and compiler/toolchain -- so that programmers could specify the additional information that is needed for metadata -- plus a supporting structure of macros, base classes, and/or ATL-like smart pointers. Correct?
If that's the question, let me do my best to shed light on it...
At the outset of the project, my team was asked by our management to take as primary design requirements that we find a programming model that should:
R1. Enable full power and control, including both consumption and authoring. It's C++'s turf to leave no room for a language lower than C++ to get at the underlying platform, and we wanted that to be true also for WinRT. There should never be a reason to use another language to be able to control or express WinRT-like things. I think(?) this is noncontroversial on this thread (correct me if I'm wrong).
R2. Be as simple and elegant as possible for the developer. In particular, the model should minimize both the quantity of the code the user has to write and the complexity of the build system he has to deal with, comparable to the other WinRT languages. The main reasons for this goal were:
I suspect that the tension in this thread is around R2, because that goal/constraint is in conflict with an ATL + MIDL like approach. As a simple example that doesn't even use properties/delegate/events, consider:
ref class Screen {
public:
int DrawLine( Point x, Point y );
};
Screen s;
s.DrawLine( Point(10,40), Point(20,50) );
In this admittedly simple authoring example, the only syntax delta from ISO C++ is "ref" and the code is all in one place; no extra tool is required, and the user just wrote a few more letters and moved on.
Two questions:
A. What is the minimal code syntax and build steps it would it take to express this in a MIDL-style approach, and across how many source/intermediate files? What's the best we could do in that kind of alternative approach?
B. How do you feel about these two goals?
Both goals are pro-ISO C++ statements, but they are different and actually in conflict -- at least, I don't know of a way to achieve both simultaneously, and we tried.
So it sounds like perhaps the fundamental tension is that this time we aimed for answer B1 but some other people would prefer answer B2 (which we aimed for in the past with ATL + MIDL). I think either choice will unfortunately disappoint some subset of developers. We have lots of experience shipping B2 and know its weaknesses and the reasons why some customers have kept telling us they don't like it; for example, people have complained equally that that's not ISO C++ either (I agree; I don't think either C++/CX style extensions or MIDL extensions/tools ends up being any more "ISO C++," and I think there's feedback about that even on this thread such as @Glen's and @C64's comments I quoted above).
Either way, it's still all nonportable proprietary extensions that are not ISO C++, just in different places and styles, and so I have sympathy for prioritizing the B1 goal of at least minimizing the quantity of it (as a subgoal of requirement R2 above). The primary reason we couldn't convince ourselves to do down the B2 path again was because every time we generated side-by-side WinRT-using examples we found it made the user's code more verbose even in the .cpp file, and added more complexity and extensions in the .idl file and compiler that would be needed, and therefore (we felt) failed to achieve R2 because it created a disincentive against using VC++ for WinRT projects which includes a disincentive against using C++ for even the non-boundary code.
There are other design goals and constraints we already mentioned, such as supporting properties/delegates/events which begs for language support and supporting tools like debuggers and design tools well, but even those are secondary to these two fundamental requirements R1 and R2 above.
GoingNative 3: The C++/CX Episode with Marian Luparu
Nov 11, 2011 at 11:19 AM@PFYB wrote: "I suspect Herb didn't read the thread. I suspect he won't. Such is the "discussion" we are having here."
Note that this is now a 32,000-word thread. That's half the word count of Exceptional C++.
So I appreciated that @PFYB agreed to identify a key question, which can reasonably be answered:
@PFYB asked: "The main question raised in the thread is: *** Why, instead of doing C++/CX, did you not use a design that requires no language extensions, eg, by generating C++ wrapper code for consuming WinRT components (similarly to #import) and generating C++ wrapper code for exposing WinRT components (the reverse of #import)? ***"
Yesterday I put aside other work to spend a couple of hours writing a thoughtful answer, without evasion and in reasonable detail, including: a pointer to detailed discussion of many of these points in my 54-page A Design Rationale for C++/CLI; that we had tried and prototyped this and other options; and summarizing some highlights of what we learned over the course of about 18 months (end to end, the intensive part was about a year), during which time WinRT itself was still in flux and we had to both influence its design and accommodate the directions it might go.
@PFYB responded in part: "I am deeply dissatisfied with the post from Herb [that answered exactly your question]. I am tired of answering the same old points ad infinitum [so evidently others have already given you the same answers to the same question]. I suspect Herb didn't read the thread. I suspect he won't. Such is the "discussion" we are having here."
Wow.
You're welcome. Sorry that I can't be helpful.
Herb
See more comments…