{"id":4873,"date":"2008-08-11T15:32:00","date_gmt":"2008-08-11T15:32:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2008\/08\/11\/tr1-fixes-in-vc9-sp1\/"},"modified":"2019-02-18T18:54:02","modified_gmt":"2019-02-18T18:54:02","slug":"tr1-fixes-in-vc9-sp1","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/tr1-fixes-in-vc9-sp1\/","title":{"rendered":"TR1 Fixes In VC9 SP1"},"content":{"rendered":"<p class=\"MsoNormal\"><span><font face=\"Verdana\">STL enjoys speaking in the third person and also enjoys bringing you this exclusive news:<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">Visual Studio 2008 Service Pack 1 (VC9 SP1) contains the TR1 and MFC library extensions that were originally released in the <a class=\"\" href=\"http:\/\/blogs.msdn.com\/vcblog\/archive\/2008\/04\/22\/visual-c-2008-feature-pack-refresh.aspx\">Visual C++ 2008 Feature Pack Refresh<\/a><\/font><font face=\"Verdana\">.&nbsp; But wait!&nbsp; VC9 SP1 also contains many delicious fixes for TR1 and MFC.&nbsp; (For TR1, &#8220;many&#8221; is 16; for MFC, &#8220;many&#8221; is 60 or more!)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">As the current maintainer of the C++ Standard Library and TR1 implementations within Microsoft, STL has compiled an exhaustive list of the TR1 fixes in VC9 SP1.&nbsp; But first!&nbsp; Shout-outs must be sent to P.J. Plauger and Christopher J. Walker of <a class=\"\" href=\"http:\/\/dinkumware.com\/\">Dinkumware<\/a><\/font><font face=\"Verdana\">, who tirelessly worked to implement most of these fixes, and Microsoft&#8217;s compiler front-end ninja <a class=\"\" href=\"http:\/\/blogs.msdn.com\/vcblog\/archive\/2008\/06\/05\/some-c-gotchas.aspx\">Jonathan Caves<\/a><\/font><font face=\"Verdana\">, who fixed nasty compiler bugs that were exposed by TR1.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">The three most significant fixes are:<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">* A massive performance improvement in regex matching.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">* An across-the-board performance improvement in STL containers of TR1 objects (e.g. vector&lt;shared_ptr&lt;T&gt; &gt;).<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">* A fix allowing tr1::function to store function objects with non-const function call operators.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">This is the exhaustive list:<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">1. The STL algorithm search_n() no longer spuriously triggers _HAS_ITERATOR_DEBUGGING assertions.&nbsp; (search_n() isn&#8217;t part of TR1, but this is why it&#8217;s being mentioned here:&nbsp; A severe search_n() bug, a regression from VC8 SP1 to VC9 RTM where the predicate version attempted to use operator==(), was fixed in the VC9 Feature Pack Refresh.&nbsp; However, the fix contained this less severe flaw, which was noticed in time to be truly fixed in VC9 SP1.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">2. The random distribution uniform_int&lt;unsigned long long&gt; no longer infinitely loops.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">3. The &lt;random&gt; header has been overhauled, incorporating many C++0x improvements.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">4. The copy constructors of the pseudorandom number generators now behave correctly.&nbsp; (This was a subtle mistake where a template constructor provided a better match than a copy constructor during overload resolution.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">5. enable_shared_from_this&#8217;s copy constructor and copy assignment operator have been corrected.&nbsp; (This affected classes deriving from enable_shared_from_this, and did not affect other uses of shared_ptr.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">6. shared_ptr&lt;const T&gt; can now be constructed from const T *.&nbsp; (This is relatively unusual.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">7. tr1::function can now store function objects with non-const function call operators.&nbsp; (This was a severe problem.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">8. The performance of regex matching has been massively improved.&nbsp; (In general, TR1 Regex is as fast or faster than Boost.Regex 1.35.0.&nbsp; TR1 Regex is still slower than Boost for some regexes, such as those dominated by alternations like &#8220;cute|fluffy|kittens&#8221;, but their performance has also improved significantly compared to the Feature Pack Refresh.&nbsp; Further performance improvements are being investigated for VC10.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">9. The performance of unordered_set (etc.) and hash_set (etc.) has been significantly improved.&nbsp; (tr1::unordered_set and stdext::hash_set share the same implementation.&nbsp; erase() still\npresents performance problems, which are being investigated for VC10.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">10. result_of now accepts references to functions.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">11. is_function and is_member_function_pointer now work correctly with variadic arguments.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">12. is_polymorphic now works correctly.&nbsp; (It previously gave bogus answers for classes like std::iostream.&nbsp; This was a compiler bug fixed by Jonathan Caves.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">13. The &lt;memory&gt; header&#8217;s declarations of the _InterlockedIncrement (etc.) intrinsics can now be suppressed by defining _DO_NOT_DECLARE_INTERLOCKED_INTRINSICS_IN_MEMORY .&nbsp; This is for compatibility with &lt;intrin.h&gt; and &lt;winbase.h&gt;, which contain conflicting declarations for certain configurations of certain platforms.&nbsp; (This workaround has been eliminated in VC10, which contains a comprehensive fix.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">14. mem_fn() now works with abstract base classes.&nbsp; (This surprising bug was caused by library and compiler bugs, both fixed.&nbsp; Other code may benefit from this compiler fix.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">15. is_pod and has_trivial_constructor now work correctly.&nbsp; (They previously gave bogus answers for certain uncommon classes.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">16. The Swaptimization (previously mentioned in <a class=\"\" href=\"http:\/\/blogs.msdn.com\/vcblog\/archive\/2008\/01\/08\/q-a-on-our-tr1-implementation.aspx\">this VCBlog post<\/a><\/font><font face=\"Verdana\">) is now actually used for TR1 objects.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">#16 deserves some explanation.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">STL containers (vector, deque, list, set, multiset, map, multimap) are &#8220;fast-swappable&#8221;; x.swap(y) and swap(x, y) are constant-time, nofail, non-iterator-invalidating.&nbsp; (You might remember that VC8&#8217;s <a class=\"\" href=\"http:\/\/blogs.msdn.com\/vcblog\/archive\/2007\/08\/10\/the-future-of-the-c-language.aspx\">Swap Bug<\/a><\/font><font face=\"Verdana\"> broke that last, very important part.)&nbsp; std::string swap() is also constant-time and nofail, although it can invalidate iterators due to the small string optimization.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">Constant-time means that swapping STL containers is implemented by swapping their guts (their pointers, whether to a vector&#8217;s block of memory, a list&#8217;s doubly-linked nodes, or a map&#8217;s binary tree nodes).&nbsp; That&#8217;s far superior to all of the element-copying that &#8220;Container temp = a; a = b; b = temp;&#8221; would involve.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">Now, when a vector undergoes reallocation, it has to copy its current elements from the old memory block to the new memory block.&nbsp; When you have a vector of STL containers (vector&lt;vector&lt;int&gt; &gt;, vector&lt;set&lt;int&gt; &gt;, etc.), that would be slow, copying the sub-containers and doing lots of dynamic memory allocation and deallocation.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">The Swaptimization, which was present in VC8 (possibly earlier, but STL hasn&#8217;t checked), is a bit of template magic whereby STL containers are marked as having fast swaps.&nbsp; When a vector&lt;T&gt; undergoes reallocation, it detects whether the T has a fast swap, and if so, will swap elements from the old memory block to the new memory block.&nbsp; This is super fast!&nbsp; (Why doesn&#8217;t it always swap?&nbsp; For vector&lt;int&gt;, simply copying ints from the old memory block to the new memory block is faster &#8211; nothing needs to be swapped back into the old memory block.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">Many TR1 objects, such as unordered_set and match_results and shared_ptr, also have fast swaps.&nbsp; This is because they&#8217;re either containers (like unordered_set) or they wrap containers (like match_results), or they&#8217;re not containers but they have the same pointers-to-stuff structure (like shared_ptr).&nbsp; So, Dinkumware and STL worked really hard to give all TR1 objects fast swaps, and mark them appropriately to be picked up by the Swaptimization.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">Unfortunately, this was simply broken in the Feature Pack Refresh!&nbsp; The problem was subtle.&nbsp; The STL provides the swap() free function in namespace std, which performs the three-step dance that works for anything copyable and assignable (but might be slow).&nbsp; The idea is that users with fast-swappable classes, in addition to providing member swap(), can fully specialize swap() in namespace std for their classes.&nbsp; (Generally, users *aren&#8217;t* supposed to add anything to namespace std.&nbsp; However, Standard templates may be fully or partially specialized for user classes; this is paragraph 17.4.3.1\/1 of the Standard.)&nbsp; This works well en\nough.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">However, users with fast-swappable class *templates* have to do something different.&nbsp; A not-commonly-understood fact about C++ is that there are no such things as partial specializations of function templates.&nbsp; Anything that looks like a partial specialization is actually an overload.&nbsp; (Only classes can be partially specialized.)&nbsp; In practice, overloads behave similarly enough to how users think partial specializations of function templates would work, and everyone gets along happily.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">But this means that you can&#8217;t add overloads of swap() to namespace std, even if you think they look like those mythical partial specializations.&nbsp; So, if you have a fast-swappable class template, you need to provide a swap() free function in the same namespace as your class template, to be found through Argument-Dependent Lookup (ADL, formerly and less descriptively called Koenig Lookup).<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">(No, this isn&#8217;t really ideal.&nbsp; Swapping is such a fundamental operation that it really ought to be recognized in the Core Language like copying &#8211; but it&#8217;s far too late to change that.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">So, TR1, which is almost but not quite part of the Standard, came along and provided a bunch of fast-swappable stuff in namespace std::tr1, and defined overloads of swap(), again within std::tr1. &nbsp;The TR1 classes were fast-swappable, annotated as such, and detected as such by the existing Swaptimization machinery within vector and a few other places.&nbsp; So why didn&#8217;t it work?<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">It turned out that the Swaptimization was being performed with a call to qualified std::swap().&nbsp; Most people don&#8217;t do C++ name lookup in their heads for fun, but the important thing to know is this: Qualified Name Lookup disables ADL.&nbsp; Uh oh!&nbsp; So, the general implementation of std::swap() (doing the slow three-step dance of copying) was chosen, instead of the specific implementations of std::tr1::swap() for shared_ptr&lt;T&gt;, unordered_set&lt;T&gt;, and so forth.&nbsp; Disaster.&nbsp; STL was deeply mortified.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">(Why was a qualified call being used?&nbsp; Another name lookup subtlety &#8211; unqualified calls like swap() activate both Unqualified Name Lookup (the usual, which everyone is familiar with) and ADL (which everyone really should be familiar with).&nbsp; Ordinarily, the union of the sets of functions they find is then used for overload resolution (picking what actually gets called).&nbsp; But if Unqualified Name Lookup finds a member function, ADL is bypassed; this is paragraph 3.4.2\/2a of the Standard.&nbsp; So, within a class that defines a member swap(), calling unqualified swap() doesn&#8217;t activate ADL, nor does it even find std::swap() &#8211; it finds the member swap().&nbsp; Thus, qualified calls became conventional within VC&#8217;s Standard Library implementation.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">The fix was to define a wrapper, std::_Swap_adl(), that calls unqualified swap(), activating ADL properly.&nbsp; The STL now calls std::_Swap_adl() whenever ADL is desired.&nbsp; (It continues to call std::swap() whenever ADL is unnecessary, such as when swapping builtins).&nbsp; As with all _Leading_underscore_capital names, users shouldn&#8217;t call std::_Swap_adl() themselves (it may change or disappear in future versions).&nbsp; You can perform the exact same trick by defining your own wrapper in your own namespace of choice, with the wrapper containing a &#8220;using namespace std;&#8221; and an unqualified call to swap().&nbsp; (If you look at std::_Swap_adl()&#8217;s implementation, it lacks a using-directive &#8211; it already lives in namespace std, unlike anything you can define.)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">The end result is that when a vector&lt;shared_ptr&lt;T&gt; &gt; undergoes reallocation, absolutely no reference counts are incremented or decremented &#8211; which is a significant performance win.&nbsp; Woot!<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">Note that none of these fixes were in the SP1 Beta, which branched for release as the Feature Pack was being finished.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font face=\"Verdana\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">Stephan T. Lavavej<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font face=\"Verdana\">Visual C++ Libraries Developer<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>STL enjoys speaking in the third person and also enjoys bringing you this exclusive news: &nbsp; Visual Studio 2008 Service Pack 1 (VC9 SP1) contains the TR1 and MFC library extensions that were originally released in the Visual C++ 2008 Feature Pack Refresh.&nbsp; But wait!&nbsp; VC9 SP1 also contains many delicious fixes for TR1 and [&hellip;]<\/p>\n","protected":false},"author":289,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4873","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus"],"acf":[],"blog_post_summary":"<p>STL enjoys speaking in the third person and also enjoys bringing you this exclusive news: &nbsp; Visual Studio 2008 Service Pack 1 (VC9 SP1) contains the TR1 and MFC library extensions that were originally released in the Visual C++ 2008 Feature Pack Refresh.&nbsp; But wait!&nbsp; VC9 SP1 also contains many delicious fixes for TR1 and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4873","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/289"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=4873"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4873\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=4873"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=4873"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=4873"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}