Hi there. Rob Huyett here again. I’m an SDET on the VC Libraries team. One of the things I’ve been working on lately is the new TR1 add-on for Visual Studio 2008. When VS 2008 TR1 support was announced about a month ago, I’m sure that the reaction varied from “Woo-hoo! I can’t wait!” to “Huh? What’s TR1? Do I care about this?” and all sorts of things in between.
This post is mostly aimed at that second category of folks – the ones who hadn’t heard about TR1, and who maybe haven’t found the time or inspiration to seek out what it’s all about. I’ll talk briefly here about just what TR1 is, and I’ll describe just a few of the TR1 features that I think are particularly nifty. This isn’t going to be an in-depth discussion or how-to manual, but it will hopefully inspire someone out there to take a closer look at what’s in TR1 and see if it can help you in your projects.
So what is TR1? Well, TR1 (“Technical Report 1”) is a set of proposed additions to the C++0x standard. Most of it will likely find its way into the new standard, but in the meantime it provides a useful stepping stone toward C++0x. TR1 is full of very useful new utilities such as new types of smart pointers (called “shared_ptr” and “weak_ptr”), new containers (tuples, unordered maps, unordered sets, and a neat STL-like array), reference wrappers, regular expression support, and function wrappers. You might look at that list and think that much of it sounds familiar. Smart pointers and function wrappers, for instance, already exist. This is true, but TR1’s versions try to be easier to use and more useful than the existing stuff… sort of like the next iteration based on a few years of experience finding out what works and what doesn’t work.
Alright, on to some specifics! First, I’d like to mention the new TR1 tuple and array classes. Then I’ll talk just a bit about shared_ptr. I’ll finish up with some information about regex, TR1’s regular expression utility. Again, people who are familiar with TR1 probably won’t get much out of this, but it will hopefully whet the appetite of those who are new to TR1.
Tuple is very much like the existing pair class, except that it can hold up to ten items instead of just two. Just like you can have pair<INT, char> p;, you can have something like tuple<INT, char, int, double, char*> t;. Handy, no?
TR1’s array class is very much like a fixed-length STL vector. Vector is a very useful class, and it is probably sufficient (even preferable) for most array-type needs. However, there are some situations where the developer is absolutely positive that the array needed will always be a particular size… no more, no less. In these cases, the variable-size feature of vector is not needed and just adds extra overhead. While you could just use a regular old C-style “square-bracket” array, the TR1 array class lets you use all of the STL-type iterators and algorithms. While it lacks some of the flexibility of a vector, it opens up more options than are available with a C-style array.
Shared_ptr is a very easy-to-use tool that greatly simplifies memory management. It all but makes new/delete combinations obsolete. Shared_ptr is a smart pointer class that is pretty easy to use. The syntax is fairly simple… shared_ptr<STRING> sp(new string(“foo”)); creates a shared_ptr called sp to a string containing “foo”. This shared_ptr will act almost just like any “normal” pointer, except that you don’t need to remember to delete it when you’re done. And unlike some older smart pointers, you don’t need to modify the target class (in this case, string) to include reference counting or anything like that… nearly any class you want will work with shared_ptr as-is. Speaking of reference counting, shared_ptr takes care of that (hence the “shared” in the name). If I were to make another shared_ptr that points to the same thing (like shared_ptr<STRING> sp2 = sp;), then shared_ptr’s reference counting is smart enough to only free up the memory when BOTH sp and sp2 are gone. Of course, this barely scratches the surface of what shared_ptr is all about, but it’s a start.
Regex is a class that lets you write complex regular expressions like those commonly used in Perl. While C++ has always had some amount of support for regular expressions, TR1’s regex utilities simplify things by building in the mechanics for parsing, matching, and capture groups. The regex class holds the actual regular expression, and algorithms such as regex_search(), regex_match(), and regex_replace() make it easy to apply that expression to a string. As you can probably deduce from the algorithm names, regex_search() tells the developer if the string contains any substrings that conform to the expression, regex_match() tells if the entire string conforms to the expression, and regex_replace() provides an easy way to change the string to fit a particular format. Regex can do quite a bit more than I’ve outlined here, but this should give you an idea of what regex is all about.
Well, that’s about all I wanted to say here. If any of this kindles some new interest in TR1 in any of the vcblog readers, great! Of course, any comments or questions that you might have will be appreciated.
Rob Huyett, VC Libraries Team
"Most of it will likely find its way into the new standard, but in the meantime it provides a useful stepping stone toward C++0x."
Or in the "meantime", perhaps you could complete C++ 1988 (ISO/IEC 14882:1998) from almost a decade ago. Hint: export (it's one of the keywords).
Sure, I'm looking forward to future versions of the standard as well, but there are still past standards that are not fully implemented even years after their finalization.
I must agree with the above poster. Please fully implement the previous standards before working on future ones.
Last month it was clarified that Microsoft would be licensing the Dinkumware implementation of TR1. So, what exactly is the Microsoft VC Libraries team doing?
If I really needed TR1, I could always license it from Dinkumware myself. Or I even code it myself. What I absolutely can not do myself is fix / implement non-conformant language issues such as export, two-phase name lookup, or exception specifications. I growing proportion of various customer's code base can no longer be compiled with Microsoft's non-conformant compilers, often forcing me to use more conformant compilers such as those from Comeau and Borland. I really do want to use VC++, so please give me a better option.
Please fully implement existing standards before jumping on future ones.
I just wanted to add some notes regarding export:
IIRC it isn't a decade old and is an extension to C++98. There are only few compilers supporting this feature and AFAIK all of them are using the EDG front end. IIRC there has been only a beta of an experimental EDG front end based compiler from Borland, the current one doesn't support export - AFAIK.
It's been said that to implement export 2-3 men years of implementation is needed and I think it doesn't pay out, to invest that much time. I rather would see VC to support a C++ module concept as soon as possible, when it becomes part of the C++ standard.
IMHO export is rarely used, but this may be only my impression. I would agree to add export support to VC too, if export would be widely used by other compilers / source code.
(Please correct me if I've made some wrong statements - I'm not 100% sure about all of them)
Forget about "export" - and do read http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1426.pdf . Sure, please do fix other bugs etc. before adding new features, but TR1 is welcome.
And Borland compiler having better C++ conformance than Visual C++? Heh, which planet are *you* living on?
I look forward to TR1.
If C++0x was introduced, I am very glad.
TR1 is nothing to make a fuss. Since boost has these libraries for years.
And yes, forget export, the better thing is setting out to implement new things introducing in C++0x, don't lag behind another compilers for years again.
More, overhaul the C compiler, it is such an antiques, till a C89 compiler.
More, overhaul the C compiler, it is such an antiques, still a C89 compiler.
Yeah, boost has had this stuff for years.
And in the end, will Microsoft's new libraries have significantly better performance, conformance, usability than already found in the boost libraries?
Why not just sign an agreement with boost to officially incorporate them into DevStudio and get back to trying to make C++ a first class language within the DevStudio environment. (WinForms must be the slowest GUI dialogs known to mankind!)
In my opinion, export templates should not be used even if support were available. Export model doesn't add anything useful. Implementing this idiotic proposal voted for by accident will just slow down compilation speed.
boost tr1 implementation is rather poor according to www.dinkumware.com
boost is a sandbox for c++ extension, not a solid library.
Btw, boost::shared_ptr uses virtual functions inside (to implement custom deleters). This is not compatible with explicit DLL loading (and unloading). shared_ptr holds a pointer with vptr pointing to address space of the DLL where shared_ptr was created. So, shared_ptr::~shared_ptr() crashes with AV if the DLL was unloaded.
Unlike people in comp.lang.c++.moderated, I cannot imagine another way to implement custom deleters, so I won't be surprised that I won't be able to use tr1 shared_ptr
"IMHO export is rarely used, but this may be only my impression."
Sure it's rarely used. If we look hard, we can find the reason. Here's the biggest reason:
"There are only few compilers supporting this feature and AFAIK all of them are using the EDG front end."
And here's why people who have one of those compilers still can't use export:
'I growing proportion of various customer's code base can no longer be compiled with Microsoft's non-conformant compilers'
(Someone else explained that part of it better in an earlier thread. When some of their customers use Microsoft compilers, they have to give their customers source code that can be compiled by Microsoft compilers.)
"More, overhaul the C compiler, it is such an
antique, still a C89 compiler."
I second this, how about implementing C99.
Hm, which compiler supports export, so that Microsoft's compiler get's non-conformant with the source code written with this compiler ? When I take a look at boost, how many workarounds there are in this library to get it compiled with the various compilers, I doubt that there is really a 100% conforming compiler. Even if there is, then all compilers should support the standard at this level too, to get really portable code without having to implement compiler workarounds.
If export would be easy to implement or add real value, then I think it would have been adopted much faster. But it hasn't.
I'm still missing essential features in C++ more than export, e.g delegates. They are now in TR1, but unfortunately only as a library extension.
I guess some details of the post disappeard due to angle brackets in HTML... <>
It's a simple solution here, avoid the boost libraries and TR1 features until their equivalent have been in VC++ for 1+ years. Try to keep your development tool set free of things not included in your core development tool (VC++). MS has lacked VC++ progress since Visual Studio 6.0, not entirely due to MS, since the C++ standards committee did not progress the language much in the last 10 years. NB: Attempting to port just about anything from the UNIX/Linux open source camp to VC++ will be difficult.
I've addressed VC's non-implementation of export, two-phase name lookup, and exception specifications before. However, I'd like to remind the minority of VC customers clamoring for these features that library developers/testers are not interchangeable with compiler front-end developers/testers. If you think that these features are valuable, and aren't convinced by arguments otherwise, then you should make your concerns known - but to the relevant people. Commenting on posts by library testers like Rob (or library devs like myself) is highly unlikely to get you anywhere.
> Last month it was clarified that Microsoft would be licensing the Dinkumware implementation of TR1.
> So, what exactly is the Microsoft VC Libraries team doing?
I'll expand on this with a VCBlog post soon, but here's a summary:
1. We're integrating TR1 into VC9, so that TR1's headers live next to the STL's headers, and TR1's separately compiled components go into msvcp90[d].dll next to the STL's separately compiled components. You won't need to do anything special to access TR1 features, and you won't need to ship a whole new DLL with your programs. You'll simply need to update the version of the CRT that's distributed with your program, just like for a VC service pack (you can think of VC9 TR1 as SP0).
2. We're making TR1 play nice with /clr and /clr:pure.
3. We're ensuring that TR1 compiles warning-free at /W4, in all supported scenarios. This includes switches like /clr, /clr:pure, /Za, /Gz, and the like.
4. We're ensuring that TR1 is /analyze-clean.
5. We're identifying bugs in TR1 and working with Dinkumware to fix them. Dinkumware's code was very solid to begin with - but as ever, more eyes find more bugs. I've even found a couple of bugs in the TR1 spec itself.
6. We're striving for performance parity with Boost. In some areas, we won't get there for VC9 TR1 (hopefully, we should for VC10), but we've already made good progress. Thanks to MS's performance testing (which Rob has been in charge of), we identified a performance problem in regex matching, which Dinkumware has sped up by 4-5x. And we've achieved performance parity for function.
7. We're identifying select C++0x features to backport into TR1 - for example, allocator support for shared_ptr and function. While not in TR1, this is important to many customers (including our own compiler).
8. Because TR1 lives alongside the STL, we can make them talk to each other in order to improve performance. For example, STL containers of TR1 types (e.g. vector<shared_ptr<T> >, vector<unordered_set<T> >) will avoid copying their elements, just as STL containers of STL containers in VC8 and VC9 avoid copying their elements. Dinkumware's standalone TR1, and (to my knowledge) Boost don't implement this optimization, because it is nonportable.
9. We're implementing IDE debugger visualizers for TR1 types. I am secretly proud of how shared_ptr's visualizer switches between "1 strong ref" and "2 strong refs".
Adding TR1 isn't as simple as dropping new headers into VC\include and calling it a day.
> If I really needed TR1, I could always license it from Dinkumware myself.
That would cost you money and time. The VC9 TR1 patch will be distributed free of charge, with no effort required on your part.
And you really need TR1. Everyone does.
> Or I even code it myself.
Are you a world expert at library programming? (If so, we're hiring!) We've *got* some of the world experts at library programming, namely Dinkumware, working on TR1 - and it's not easy. Take a look at TR1 mem_fn()/bind()/function's implementation when we release the TR1 beta, and then tell me that you could write that yourself. :-)
I consider myself lucky to be able to *understand* what most of the TR1 implementation does - but I certainly don't fool myself into thinking that I could write it from scratch - well, not without dedicating several years to it and nothing else.
> I look forward to TR1.
> If C++0x was introduced, I am very glad.
VC9 TR1 isn't introducing any compiler changes.
> TR1 is nothing to make a fuss. Since boost has these libraries for years.
If you are using Boost, that's great. However, many companies are reluctant to use open-source code, even given Boost's extremely permissive license and excellent reputation. Programmers at those companies will be really happy to have VC9 TR1.
> boost is a sandbox for c++ extension, not a solid library.
I must disagree with this - I have found Boost to be extremely high quality, in terms of both correctness and performance. This isn't too surprising, since the Boost developers are also world experts at library programming.
> Btw, boost::shared_ptr uses virtual functions inside (to implement custom deleters).
> This is not compatible with explicit DLL loading (and unloading).
I'm not sure what you're saying here. If you create a shared_ptr with a custom deleter that lives inside a DLL that gets unloaded, of course the thing is going to blow up. Nothing can save you from that.
Or are you saying something else?
> When I take a look at boost, how many workarounds there are
> in this library to get it compiled with the various compilers
Boost is special because some of its libraries still attempt to provide limited support for VC6 (the Infinite Enemy of modern C++ programming - GCC 2.x was also bad, but it apparently doesn't have eternal unlife). This is presumably highly appreciated by those people who still use VC6 despite the fact that Microsoft no longer supports it, and presumably contributes to Boost's widespread use and reputation for working anywhere - but it certainly makes the implementation of those libraries more complex.
> I doubt that there is really a 100% conforming compiler.
There isn't - but Comeau comes close. That's one of their main selling points, after all.
> I'm still missing essential features in C++ more than export, e.g delegates.
> They are now in TR1, but unfortunately only as a library extension.
Unlike other languages, C++ prefers to provide powerful support in the core language for library implementation, instead of providing such functionality directly in the core language. This contributes to C++'s extreme flexibility and generality.
What you call "delegates" in the managed world, I call "bound functors". TR1 binders are psychotically powerful. You just have to learn a different way of looking at things.
> It's a simple solution here, avoid the boost libraries and TR1
> features until their equivalent have been in VC++ for 1+ years.
I disagree - Boost is highly stable, and TR1 will be immediately usable - if not, Rob and I haven't done our jobs (and since there will be a TR1 beta, you won't either).
> Try to keep your development tool set free of things not included in your core development tool (VC++).
I'm trying to imagine how anyone could get anything done in C++ without third-party libraries, and failing.
> MS has lacked VC++ progress since Visual Studio 6.0
This is completely untrue.
VC's compiler and library conformance has increased MASSIVELY from the blighted VC6, through VC7/VC7.1, to VC8. (VC9 further improved conformance, although not nearly as much as the 6 => 7.1 and 7.1 => 8 leaps).
> Attempting to port just about anything from the UNIX/Linux open source camp to VC++ will be difficult.
Some of that, it is true, is due to VC bugs and quirks. A lot of it is due to Unixisms. Try compiling GNU tar for Windows and see how far you get.
(On the other hand, other programs are equally at home on Unixes and Windows - my usual favorite being bzip2. Portable programming pays!)
Stephan T. Lavavej
Visual C++ Libraries Developer, working on TR1