C++11 Features in Visual C++ 11

C++11 Features in Visual C++ 11

UPDATE - March 2, 2012: the range-based for-loop and override/final v1.0 have been implemented in VC11 Beta.

 

There's a new C++ Standard and a new version of Visual C++, and it's time to reveal what features from the former we're implementing in the latter!

Terminology notes: During its development, the new C++ Standard was (optimistically) referred to as C++0x.  It's finally being published in 2011, and it's now referred to as C++11.  (Even International Standards slip their release dates.)  The Final Draft International Standard is no longer publicly available.  It was immediately preceded by Working Paper N3242, which is fairly close in content.  (Most of the people who care about the differences are compiler/Standard Library devs who already have access to the FDIS.)  Eventually, I expect that the C++11 Standard will be available from ANSI, like C++03 is.

As for Visual C++, it has three different version numbers, for maximum fun.  There's the branded version (printed on the box), the internal version (displayed in Help About), and the compiler version (displayed by cl.exe and the _MSC_VER macro - this one is different because our C++ compiler predates the "Visual" in Visual C++).  For example:

VS 2005 == VC8 == _MSC_VER 1400
VS 2008 == VC9 == _MSC_VER 1500
VS 2010 == VC10 == _MSC_VER 1600

The final branding for the new version hasn't been announced yet; for now, I'm supposed to say "Visual C++ in Visual Studio 11 Developer Preview".  Internally, it's just VC11, and its _MSC_VER macro is 1700.  (That macro is of interest to people who want to target different major versions of VC and emit different code for them.)  I say VC10 and VC11 because they're nice and simple - the 11 in VC11 does not refer to a year.  (VS 2010 == VC10 was a confusing coincidence.)

If you read C++0x Core Language Features In VC10: The Table last year, the following table will look familiar to you.  This time, I started with GCC's table again, but I reorganized it more extensively for increased accuracy and clarity (as many features went through significant revisions):

 

C++11 Core Language Features VC10 VC11
Rvalue references v0.1, v1.0, v2.0, v2.1, v3.0 v2.0 v2.1*
ref-qualifiers No No
Non-static data member initializers No No
Variadic templates v0.9, v1.0 No No
Initializer lists No No
static_assert Yes Yes
auto v0.9, v1.0 v1.0 v1.0
Trailing return types Yes Yes
Lambdas v0.9, v1.0, v1.1 v1.0 v1.1
decltype v1.0, v1.1 v1.0 v1.1**
Right angle brackets Yes Yes
Default template arguments for function templates No No
Expression SFINAE No No
Alias templates No No
Extern templates Yes Yes
nullptr Yes Yes
Strongly typed enums Partial Yes
Forward declared enums No Yes
Attributes No No
constexpr No No
Alignment TR1 Partial
Delegating constructors No No
Inheriting constructors No No
Explicit conversion operators No No
char16_t and char32_t No No
Unicode string literals No No
Raw string literals No No
Universal character names in literals No No
User-defined literals No No
Standard-layout and trivial types No Yes
Defaulted and deleted functions No No
Extended friend declarations Yes Yes
Extended sizeof No No
Inline namespaces No No
Unrestricted unions No No
Local and unnamed types as template arguments Yes Yes
Range-based for-loop No Yes
override and final v0.8, v0.9, v1.0 Partial Yes
Minimal GC support Yes Yes
noexcept No No

 

C++11 Core Language Features: Concurrency VC10 VC11
Reworded sequence points N/A N/A
Atomics No Yes
Strong compare and exchange No Yes
Bidirectional fences No Yes
Memory model N/A N/A
Data-dependency ordering No Yes
Data-dependency ordering: function annotation No No
exception_ptr Yes Yes
quick_exit and at_quick_exit No No
Atomics in signal handlers No No
Thread-local storage Partial Partial
Magic statics No No

 

C++11 Core Language Features: C99 VC10 VC11
__func__ Partial Partial
C99 preprocessor Partial Partial
long long Yes Yes
Extended integer types N/A N/A

 

Here's a quick guide to this table, but note that I can't explain everything from scratch without writing a whole book, so this assumes moderate familiarity with what's in C++11:

Rvalue references: N1610 "Clarification of Initialization of Class Objects by rvalues" was an early attempt to enable move semantics without rvalue references.  I'm calling it "rvalue references v0.1", as it's of historical interest only.  It was superseded by rvalue references v1.0, the original wording.  Rvalue references v2.0, which is what we shipped in VC10 RTM/SP1, prohibits rvalue references from binding to lvalues, fixing a major safety problem.  Rvalue references v2.1 refines this rule.  Consider vector<string>::push_back(), which has the overloads push_back(const string&) and push_back(string&&), and the call v.push_back("meow").  The expression "meow" is a string literal, and it is an lvalue.  (All other literals like 1729 are rvalues, but string literals are special because they're arrays.)  The rvalue references v2.0 rules looked at this and said, string&& can't bind to "meow" because "meow" is an lvalue, so push_back(const string&) is the only viable overload.  This would create a temporary std::string, copy it into the vector, then destroy the temporary std::string.  Yuck!  The rvalue references v2.1 rules recognize that binding string&& to "meow" would create a temporary std::string, and that temporary is an rvalue.  Therefore, both push_back(const string&) and push_back(string&&) are viable, and push_back(string&&) is preferred.  A temporary std::string is constructed, then moved into the vector.  This is more efficient, which is good!  (Yes, I'm ignoring the Small String Optimization here.)

The table says "v2.1*" because these new rules haven't been completely implemented in the VC11 Developer Preview.  This is being tracked by an active bug.  (Indeed, this is a Standard bugfix.)

Rvalue references v3.0 adds new rules to automatically generate move constructors and move assignment operators under certain conditions.  This will not be implemented in VC11, which will continue to follow VC10's behavior of never automatically generating move constructors/move assignment operators.  (As with all of the not-yet-implemented features here, this is due to time and resource constraints, and not due to dislike of the features themselves!)

(By the way, all of this v0.1, v1.0, v2.0, v2.1, v3.0 stuff is my own terminology, which I think adds clarity to C++11's evolution.)

Lambdas: After lambdas were voted into the Working Paper (v0.9) and mutable lambdas were added (v1.0), the Standardization Committee overhauled the wording, producing lambdas v1.1.  This happened too late for us to implement in VC10, but we've already implemented it in VC11.  The lambdas v1.1 wording clarifies what should happen in corner cases like referring to static members, or nested lambdas.  This fixes a bunch of bugs triggered by complicated lambdas.  Additionally, stateless lambdas are now convertible to function pointers in VC11.  This isn't in N2927's wording, but I count it as part of lambdas v1.1 anyways.  It's FDIS 5.1.2 [expr.prim.lambda]/6: "The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator."  (It's even better than that, since we've made stateless lambdas convertible to function pointers with arbitrary calling conventions.  This is important when dealing with APIs that expect __stdcall function pointers and so forth.)

decltype: After decltype was voted into the Working Paper (v1.0), it received a small but important bugfix at the very last minute (v1.1).  This isn't interesting to most programmers, but it's of great interest to programmers who work on the STL and Boost.  The table says "v1.1**" because this isn't implemented in the VC11 Developer Preview, but the changes to implement it have already been checked in.

Strongly typed/forward declared enums: Strongly typed enums were partially supported in VC10 (specifically, the part about explicitly specified underlying types), and C++11's semantics for forward declared enums weren't supported at all in VC10.  Both have been completely implemented in VC11.

Alignment: Neither VC10 nor VC11 implement the Core Language keywords alignas/alignof from the alignment proposal that was voted into the Working Paper.  VC10 had aligned_storage from TR1.  VC11 adds aligned_union and std::align() to the Standard Library.

Standard-layout and trivial types: As far as I can tell, the user-visible changes from N2342 "POD's Revisited; Resolving Core Issue 568 (Revision 5)" are the addition of is_trivial and is_standard_layout to <type_traits>.  (N2342 performed a lot of surgery to Core Language wording, but it just makes stuff well-defined that users could have gotten away with anyways, hence no compiler changes are necessary.)  We had these type traits in VC10, but they just duplicated is_pod, so I'm calling that "No" support.  In VC11, they're powered by compiler hooks that should give accurate answers.

Extended friend declarations: Last year, I said that VC10 partially supported this.  Upon closer inspection of N1791, I've determined that VC's support for this is essentially complete (it doesn't even emit "non-Standard extension" warnings, unlike some of the other Ascended Extensions in this table).  So I've marked both VC10 and VC11 as "Yes".

override and final: This went through a short but complicated evolution.   Originally (v0.8) there were [[override]], [[hiding]], and [[base_check]] attributes.  Then (v0.9) the attributes were eliminated and replaced with contextual keywords.  Finally (v1.0), they were reduced to "final" on classes, and "override" and "final" on functions.  This makes it an Ascended Extension, as VC already supports this "override" syntax on functions, with semantics reasonably close to C++11's.  "final" is also supported, but under the different spelling "sealed".  This qualifies for "Partial" support in my table.

Minimal GC support: As it turns out, N2670's only user-visible changes are a bunch of no-op Standard Library functions, which we already picked up in VC10.

Reworded sequence points: After staring at N2239's changes, replacing C++98/03's "sequence point" wording with C++11's "sequenced before" wording (which is more useful, and more friendly to multithreading), there appears to be nothing for a compiler or Standard Library implementation to do.  So I've marked this as N/A.

Atomics, etc.: Atomics, strong compare and exchange, bidirectional fences, and data-dependency ordering specify Standard Library machinery, which we're implementing in VC11.

Memory model: N2429 made the Core Language recognize the existence of multithreading, but there appears to be nothing for a compiler implementation to do (at least, one that already supported multithreading).  So it's N/A in the table.

Extended integer types: N1988 itself says: "A final point on implementation cost: this extension will probably cause no changes in most compilers. Any compiler that has no integer types other than those mandated by the standard (and some version of long long, which is mandated by the N1811 change) will likely conform already."  Another N/A feature!

That covers the Core Language.  As for the Standard Library, I don't have a pretty table of features, but I do have good news:

In VC11, we intend to completely support the C++11 Standard Library, modulo not-yet-implemented compiler features.  (Additionally, VC11 won't completely implement the C99 Standard Library, which has been incorporated by reference into the C++11 Standard Library.  Note that VC10 and VC11 already have <stdint.h>.)  Here's a non-exhaustive list of the changes we're making:

New headers: <atomic>, <chrono>, <condition_variable>, <future>, <mutex>, <ratio>, <scoped_allocator>, and <thread>.  (And I've removed the broken <initializer_list> header that I accidentally left in VC10.)

Emplacement: As required by C++11, we've implemented emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after() in all containers for "arbitrary" numbers of arguments (see below).  For example, vector<T> has "template <typename... Args> void emplace_back(Args&&... args)" which directly constructs an element of type T at the back of the vector from an arbitrary number of arbitrary arguments, perfectly forwarded.  This can be more efficient than push_back(T&&), which would involve an extra move construction and destruction.  (VC10 supported emplacement from 1 argument, which was not especially useful.)

Faux variadics: We've developed a new scheme for simulating variadic templates.  Previously in VC9 SP1 and VC10, we repeatedly included subheaders with macros defined differently each time, in order to stamp out overloads for 0, 1, 2, 3, etc. arguments.  (For example, <memory> included the internal subheader <xxshared> repeatedly, in order to stamp out make_shared<T>(args, args, args).)  In VC11, the subheaders are gone.  Now we define variadic templates themselves as macros (with lots of backslash-continuations), then expand them with master macros.  This internal implementation change has some user-visible effects.  First, the code is more maintainable, easier to use (adding subheaders was a fair amount of work), and slightly less hideously unreadable.  This is what allowed us to easily implement variadic emplacement, and should make it easier to squash bugs in the future.  Second, it's harder to step into with the debugger (sorry!).  Third, pair's pair(piecewise_construct_t, tuple<Args1...>, tuple<Args2...>) constructor had "interesting" effects.  This requires N^2 overloads (if we support up to 10-tuples, that means 121 overloads, since empty tuples count here too).  We initially observed that this (spamming out so many pair-tuple overloads, plus all of the emplacement overloads) consumed a massive amount of memory during compilation, so as a workaround we reduced infinity.  In VC9 SP1 and VC10, infinity was 10 (i.e. "variadic" templates supported 0 to 10 arguments inclusive).  In the VC11 Developer Preview, infinity is 5 by default.  This got our compiler memory consumption back to what it was in VC10.  If you need more arguments (e.g. you had code compiling with VC9 SP1 or VC10 that used 6-tuples), there's an escape hatch.  You can define _VARIADIC_MAX project-wide between 5 and 10 inclusive (it defaults to 5).  Increasing it will make the compiler consume more memory, and may require you to use the /Zm option to reserve more space for PCHes.

This story has a happy ending, though!  Jonathan Caves, our compiler front-end lord, investigated this and found that something our tuple implementation was doing (specifically, lots of default template arguments), multiplied by pair's N^2 overloads, multiplied by how much pair tends to get used by STL programs (e.g. every map), was responsible for the increased memory consumption.  He fixed that, and the fix is making its way over to our STL branch.  At that point, we'll see if we can raise the _VARIADIC_MAX default to 10 again (as I would prefer not to break existing code unnecessarily).

Randomness: uniform_int_distribution is now perfectly unbiased, and we've implemented shuffle() in <algorithm>, which directly accepts Uniform Random Number Generators like mersenne_twister.

Resistance to overloaded address-of operators: C++98/03 prohibited elements of STL containers from overloading their address-of operator.  This is what classes like CComPtr do, so helper classes like CAdapt were required to shield the STL from such overloads.  During VC10's development, while massively rewriting the STL (for rvalue references, among other things), our changes made the STL hate overloaded address-of operators even more in some situations.  (You might remember one of my VCBlog posts about this.)  Then C++11 changed its requirements, making overloaded address-of operators acceptable.  (C++11, and VC10, provide the helper function std::addressof(), which is capable of getting the true address of an object regardless of operator overloading.)  Before VC10 shipped, we attempted to audit all STL containers for occurrences of "&elem", replacing them with "std::addressof(elem)" which is appropriately resistant.  In VC11, we've gone further.  Now we've audited all containers and all iterators, so classes that overload their address-of operator should be usable throughout the STL.  Any remaining problems are bugs that should be reported to us through Microsoft Connect.  (As you might imagine, grepping for "&elem" is rather difficult!)  I haven't audited the algorithms yet, but a casual glance indicated to me that they aren't especially fond of taking the addresses of elements.

We're also going beyond C++11 in a couple of ways:

SCARY iterators: As permitted but not required by the C++11 Standard, SCARY iterators have been implemented, as described by N2911 "Minimizing Dependencies within Generic Classes for Faster and Smaller Programs" and N2980 "SCARY Iterator Assignment and Initialization, Revision 1".

Filesystem: We've added the <filesystem> header from the TR2 proposal, featuring super-cool machinery like recursive_directory_iterator.  Note that the 2006 proposal (before work on TR2 was frozen due to C++0x running extremely late and turning into C++11) was derived from Boost.Filesystem V2.  It later evolved into Boost.Filesystem V3, but that will not be implemented in VC11.

Finally, in addition to numerous bugfixes, we've performed a major optimization!  All of our containers (loosely speaking) are now optimally small given their current representations.  This is referring to the container objects themselves, not their pointed-to guts.  For example, vector contains three raw pointers.  In VC10, x86 release mode, vector was 16 bytes.  In VC11, it's 12 bytes, which is optimally small.  This is a big deal if you have 100,000 vectors in your program - VC11 will save you 400,000 bytes.  Decreased memory usage saves both space and time.

This was achieved by avoiding the storage of empty allocators and comparators, as std::allocator and std::less are stateless.  (We'll activate these optimizations for custom allocators/comparators too, as long as they're stateless.  Obviously, we can't avoid storing stateful allocators/comparators, but those are quite rare.)

Here are all of the sizes for x86 and x64.  (32-bit ARM is equivalent to x86 for these purposes).  Naturally, these tables cover release mode, as debug mode contains checking machinery that consumes space and time.  I have separate columns for VC9 SP1, where _SECURE_SCL defaulted to 1, and for VC9 SP1 with _SECURE_SCL manually set to 0 for maximum speed.  VC10 and VC11 default _SECURE_SCL to 0 (now known as _ITERATOR_DEBUG_LEVEL).

 

x86 Container Sizes (Bytes) VC9 SP1 VC9 SP1
SCL=0
VC10 VC11
vector<int> 24 16 16 12
array<int, 5> 20 20 20 20
deque<int> 32 32 24 20
forward_list<int> N/A N/A 8 4
list<int> 28 12 12 8
priority_queue<int> 28 20 20 16
queue<int> 32 32 24 20
stack<int> 32 32 24 20
pair<int, int> 8 8 8 8
tuple<int, int, int> 16 16 16 12
map<int, int> 32 12 16 8
multimap<int, int> 32 12 16 8
set<int> 32 12 16 8
multiset<int> 32 12 16 8
hash_map<int, int> 72 44 44 32
hash_multimap<int, int> 72 44 44 32
hash_set<int> 72 44 44 32
hash_multiset<int> 72 44 44 32
unordered_map<int, int> 72 44 44 32
unordered_multimap<int, int> 72 44 44 32
unordered_set<int> 72 44 44 32
unordered_multiset<int> 72 44 44 32
string 28 28 28 24
wstring 28 28 28 24

 

x64 Container Sizes (Bytes) VC9 SP1 VC9 SP1
SCL=0
VC10 VC11
vector<int> 48 32 32 24
array<int, 5> 20 20 20 20
deque<int> 64 64 48 40
forward_list<int> N/A N/A 16 8
list<int> 56 24 24 16
priority_queue<int> 56 40 40 32
queue<int> 64 64 48 40
stack<int> 64 64 48 40
pair<int, int> 8 8 8 8
tuple<int, int, int> 16 16 16 12
map<int, int> 64 24 32 16
multimap<int, int> 64 24 32 16
set<int> 64 24 32 16
multiset<int> 64 24 32 16
hash_map<int, int> 144 88 88 64
hash_multimap<int, int> 144 88 88 64
hash_set<int> 144 88 88 64
hash_multiset<int> 144 88 88 64
unordered_map<int, int> 144 88 88 64
unordered_multimap<int, int> 144 88 88 64
unordered_set<int> 144 88 88 64
unordered_multiset<int> 144 88 88 64
string 40 40 40 32
wstring 40 40 40 32

 

Stephan T. Lavavej
Visual C++ Libraries Developer

  • @Glen : *applause*

    I agree wholeheartedly, and I hope MS sees the truth in your statements.

  • @Glen: My hat's off to you man for putting some absolute common sense back into this thread.

  • Here's an update on the state of _VARIADIC_MAX:

    JonCaves' fix arrived in my STL branch, and it has significantly reduced compiler memory consumption. When including all STL headers into a PCH (which is just a snapshot of the compiler's memory) with VC10 SP1 and VC11, using the same set of headers for a fair comparison (i.e. excluding the headers new to VC11), I observe that VC10 SP1 consumed 29.3 MB, while VC11 now consumes between 24.3 MB for N=5 and 38.7 MB for N=10. The increase from 29.3 MB to 38.7 MB is expected, because VC11's STL is still throwing more code at the compiler (all of those emplacement and pair overloads), even though the compiler's handling it more efficiently now.

    For the time being, I'm going to leave _VARIADIC_MAX's default at 5. As I mentioned in the post, this has the undesirable effect of requiring users who need more arguments to increase the setting from its default value. However, for users where N=5 is sufficient, it has the highly desirable effects of increasing compiler speed and decreasing compiler memory consumption compared to VC10 SP1 (from 29.3 MB down to 24.3 MB). Both issues have concerned me since we started simulating variadic templates in VC9 SP1. This will avoid build breaks caused by running out of PCH space. Additionally, this will avoid incomprehensible warnings about long mangled names being truncated - which I ran into in VC's own build when I tried increasing _VARIADIC_MAX back to 10, and which I really don't want to inflict on users.

    The issue here is that the STL occasionally repeats type names in templates. Sometimes this is necessary - map<K, V> is really map<K, V, less<K>, allocator<pair<const K, V>>> and that repeats K 3 times and V 2 times. I refer to this as "type multiplication" - observe that a map of maps (or a triply nested map, etc.) multiplies the type names involved even more strongly. When the type names involved are lengthy to begin with (e.g. in deeply nested namespaces, and/or deeply templated), the STL's type multiplication can cause mangled names to exceed a 4096 character limit, which triggers compiler warnings because they get truncated in a way that doesn't break the program, but interferes with debugging. We ran into this when we implemented SCARY iterators, and changed our code to avoid type multiplication there. But it still happens in <functional> (some is necessary, some is probably avoidable - but the code is difficult to change either way), and increasing _VARIADIC_MAX amplifies the effect.

    I will reconsider this decision if I hear that many users need to increase _VARIADIC_MAX. So far, I've seen only one report on Connect, and a couple of reports within Microsoft.

  • @Stephan

    I was wondering - how much of an impact would it be to increase the _VARIADIC_MAX to say about 40? In terms bot of memory and speed?

    Veriadic templates - or rather tuples are a very good tool to build a entity/component management system for a game, but then you get to double digits in the terms of tuple members.

  • barsiwek> I was wondering - how much of an impact would it be to increase the _VARIADIC_MAX to say about 40?

    Try to imagine all life as you know it stopping instantaneously and every molecule in your body exploding at the speed of light.

    Somewhat more seriously, that would give pair 1,681 piecewise_construct_t constructors. Memory consumption would be unbearable, or close to it, for the x86-hosted compilers (x86 native, x86 => x64 cross, x86 => ARM cross). The x64 native compiler would survive, but the compilation speed would be abysmal.

    The ultimate limit of 10 is somewhat arbitrary (it's what we provided in VC9 SP1 and VC10), but we really can't go much higher. If I could give you more, I would.

  • I built a private-build Tuple class, which can support up to 64 template-parameters, as part of my library...

    cppwindowsapi.codeplex.com

  • @Stephan Thank you for the answer. Since I also seem to have an idea where the numbers come form I suspect that variadic templates (when they will be available) will make everyones lives a lot easier.

    I also like the comparison to the molecule explosion :)

    @Simon I think I will either have to use a solution like yours or roll out my own. I actually have done something like that a while back - I took the tuple class from stdlib of GCC and ported it to MSVC10 using Boost.Preprocessor. All the boost test work on it and I can make it as big as I want the only problem is - it compiles soooooooo long.

  • @barsiwek:  "I took the tuple class from stdlib of GCC and ported it to MSVC10 using Boost.Preprocessor. All the boost test work on it and I can make it as big as I want the only problem is - it compiles soooooooo long."

    I assume you're aware that when separated from GCC, such a libstdc++ derived header can only be used to compile GPL-licensed code?

  • @S. Colcord: Hi - yes, I'm aware of that. Also GPL license applies if I ever want to release a piece of software that uses this class, which I won't do because of the mentioned unberable compile times (call it a failed experiment if you will).

    So no worries - GPL, GCC and libstd++ are safe.

  • @barsiwek: It tooks too much time to decode any specialized of one Tuple class in the Boost version's. Yet the Boost still limited the count of template parameters up to 256.(As you can see, i can expand mine to that also but i didn't and won't do that still)

    ----

     But the major problem is that you have to comment all existing template parameters to the compiler instead of only severals you concern currently, which also means that you have to keep everything for rare-only usage as building glass shackes along all the streets to prevent sombody getting wet in the rain. But(again), you still can't refuse to given 'enough' space for that rare usage because there is still possible of meeting the deadline to use more than original count limit(and reasonable at that time)... Unless you given the real native-variadic-template supporting. And still, the compiler can take the mechanism to limit the number of parameters at native formal because the n.v.t is NOT ask compiler to accept Unlimited count.

     I think even the 20 for _VARIADIC_MAX in MS version is still not enough. You can't just cut everything beyond the normal off, Like an old computer that equipped small memory-modules running small applications WITHOUT the disc-paging-file participating the virtual-memory.

     The number of parameters for a function from a library that built by other authors is unpredictable, You would tire to name a structure as a parameters package(And in C-only way :-( ) for you to pass parameters from agent callers to it's target to extract. But if we use tuple, we will be able to do such things easily in C++ way and won't be worry about 'What should it be the proper name of a user-defined temporary param-express-delivery?'.

  • @barsiwek: It took much time to decode any specialized of one Tuple class in the Boost version's. Yet the Boost still limited the count of template parameters to 256.(As you can see, i can expand mine to that also but i didn't and won't do that still)

    ----

     But the major problem is that you have to comment all existing template parameters to the compiler instead of only severals you concern currently, which also means that you have to keep everything for rare-only usage as building glass shackes along all the streets to prevent sombody getting wet in the rain. But (again...), you still can't simply refuse to provide 'enough' space for any rare usage because it is still possible of meeting the deadline of exceeding original count limit(and reasonable at that time)... Unless you have given the real native-variadic-template supporting. And still, the compiler can provide the mechanism to limit the number of parameters at native formal because the n.v.t does NOT ask compiler to accept Unlimited count.

     I think even the 20 for _VARIADIC_MAX in MS version is still not enough. You can't just cut everything beyond the normal off, Like an old computer that equipped small memory-modules running small applications WITHOUT the disc-paging-file participating the virtual-memory.

     The number of parameters for a function from a library that built by other authors is unpredictable, You would tire to name a structure as a parameters package(And in C-only way :-( ) for you to pass parameters from agent callers to it's target to extract. But if we use tuple, we will be able to do such things easily in C++ way and won't be worry about 'What should it be the proper name of a user-defined temporary param-express-delivery?'.

  • My employer is active MSDN subscriber. Can we request some feature from C99 to be implemented (vscanf)? Should we send email or something?

  • One word: Pathetic.

    Everything else that needed to be said is already said.

  • wiki.apache.org/.../C%2B%2B0xCompilerSupport

    Intel, GCC, Clang are all far ahead from MSVC.

  • Will you add erf, erfc, lgamma and tgamma to math.h ?

Page 10 of 11 (151 items) «7891011