What are some opinions on a C/C++ merger? Will this truly ever happen?
Printable View
What are some opinions on a C/C++ merger? Will this truly ever happen?
What C/C++ merger? They're different languages with different goals.
I wouldn't say the goals are that much different. They are both general purpose programming language. It wasn't my idea. Bjarne Strosoup first said it. I was just curious how serious this is and if it might actually happen.
If C and C++ merged, the result would be C++. So what's the point?
Practically all there is bad in C++ is because the language is based on C. That also seems to be the reason why C++ became popular.
>>If C and C++ merged, the result would be C++. So what's the point?
I like the name C.
C++ is, as pointed out, derived from C. It has many of C's features (like it or not - but it's also a reason why C++ is successful. Bjarne Stroustrup came up with the idea of C++ becasue he wanted some of the features of Simula-67, but the speed of C - so if someone asked "what do you get if you mix Simula with C" the answer would be "something like C++").
All computer languages have a variety of strong points and weak points. C and C++ are very similar in the sense that they are low-level languages (relatively speaking) and it is up to the programmer to solve many issues that higher level languages solve for the programmer - but this also means that the programmer have no control over those aspects. In Bjarne's case, it was the memory allocation, or rather, the garbage collector, that causes problems, by running for a substantial amount of the run-time of the application (more than 50%) once sufficient amount of memory had been allocate. C and C++ doesn't have garbage collection [by default], so the programmer doesn't have to fight a garbage collection mechanism coming in and "interrupting the program itself".
C is picking valuable bits from C++ when it's suitable, but merging C and C++ would just end up with C++ - otherwise there would be a loss in the merge.
There is something called "Embedded C++" that is somewhat standardized, and is a stripped down version of C++ - although I found that some useful things [namespaces for example] where removed "because they confuse the programmer". Now I don't see that as particularly confusing, but that is perhaps an individual view.
--
Mats
I don't really agree that merging C and C++ would produce C++.
There is the politics of standardisation. C++ was designed with backward compatibility to the 1989 C standard, so those who use C89 or C++ would have few problems due to incompatibilities. However, C99 was not designed with backward compatibility to C++ in mind In fact, some language features of C99 have the same name as library features in C++, and the two are not interchangeable. Philosophically, C is designed as a low level language with a (relatively) few libraries, and the intent is that new capabilities will be added to the language first with some library support if necessary. C++, on the other hand, is designed as a language that supports abstraction, and the intent is most new features will be added by expanding the standard library, with some changes to the base language only if absolutely necessary. There are merits in both approaches but, politically, finding a middle ground between advocates of both approaches would be challenging -- each would have to give up some of the core strengths of their preferred language in order to merge them.
As an example: There would be considerable debate over things like an implicit conversion from a void pointer to another pointer type: C allows the implicit conversion in the interests of type safety, C++ disallows the implicit conversion also in the interests of type safety. Code in both languages would break, with a need for clumsy workarounds, if the approach of the other was adopted.
Details. C++ is C89 with additional features, except for some minor details. C99 adds various features to C, but only variadic macros aren't in some form (not necessarily compatible) already in C++98, and they will be adopted in C++0x. Variable-length arrays are covered by vector, although the implementation does differ considerably. The built-in complex datatype is covered by C++'s library complex class. Inlines and C++-style comments are already in C++. Most of C99's library updates will be in C++0x.
As a result, if you merge C++0x and C99, feature-wise the result will be C++0x. There may be discussion whether the C or the C++ way of doing things is correct in some details, but that won't change the feature list.
Philosophy-wise the result would be a blob without purpose, which is one more reason why they shouldn't be merged.
I'd just be happy if everyone agreed that designated initializers were as great as I think they are. I can't believe some of the popular compilers that don't support them yet. :confused:
What are designated initializers?
Designated initializers is a C99 feature where you can initialize members or elements individually by name or location (in the case of arrays).
http://publib.boulder.ibm.com/infoce...esignators.htm
See also C99 6.7.8.
Ah. Oh, well. That's what constructors are for.
Designated initializers. It's one of those things that a computer can do much better than a living person. I just have to tell it which element(s) I want initialized to what, and the layout is taken care of. Reduces errors, maintenance overhead, maintenance risk (if someone switches member order in a struct), increases readability A LOT, and no runtime overhead at all.
I don't know why these have been received with such lukewarm enthusiasm. I tell most people about them, and I get either a shoulder shrug, or a "hmm, that's nice." Whatever. :rolleyes:
Ok how about something at the other end. Is there any time in the near future when C++ might break compatibility with C(I mean something more than the slight new features of C99)?
PS. I think designated initializers would be more use to a C programmer. I agree with CornedBee that that is what constructors are for.
> I don't know why these have been received with such lukewarm enthusiasm.
I think it's because they're so verbose. That's why I'm kind of 'eh' about them. It's not much less typing than using assignment operators in separate statements.
O_o
How do designated initializers require no runtime overhead? That's magic that is...
Soma
Assignment is not initialization!
The array example I showed above is more verbose than that initialization without DI? Hardly. It is far less than writing out an entire table of zeros with three elements changed, and have fun counting as well.
I'm afraid you will have to give me an example of what you mean by verbose DI.
Fair enough. I wasn't too clear about that.
What I meant to say, was that they aren't going to incur any more runtime overhead than the old-fashioned initialization.
That is what I meant to compare. Thanks for pointing that out. :)Code:struct foo {
int a, b, c, d, e, f;
};
// with DI
foo bar = { .f = 10 };
// without DI
foo bar = {0,0,0,0,0,10};
Ah... well, that depends rather a lot on whether or not you are interested in every member of a structure. (I'm thinking or any given variant of the ridiculous "object oriented" crimes perpetrated on C where every structure had members nothing ever reads or writes.)Quote:
What I meant to say, was that they aren't going to incur any more runtime overhead than the old-fashioned initialization.
In C++...Quote:
Assignment is not initialization!
You could do it with the preprocessor in classic C89 simpler, in use obviously, than C99 with designated initializers.Quote:
The array example I showed above is more verbose than that initialization without DI?
Note: I actually have no problem with designated initializers, but then I use C++ and have RAII.
Soma
> Assignment is not initialization!
Correct, but in almost all instances, you can use assignment instead of initialization.
> The array example I showed above is more verbose than that initialization without DI? Hardly. It is far less than writing out an entire table of zeros with three elements changed, and have fun counting as well.
Yes, that is a good application for that.
> I'm afraid you will have to give me an example of what you mean by verbose DI.
I mean versus C89 initialization.Code:struct a inst = { 0, 'a', "string", something.c };
struct a inst = { .id = 0, .some_char = 'a', .some_string = "string", .some_other_variable = something.c };
Why does that depend? Whether you use old-fashioned initialization or DI, anything not specified is default initialized. I don't understand the dependence that you are pointing out here.
Period. Simple assignment and initialization are two different things in both C and C++. Assignment destroys a previous value, initialization never does. You can't assign to an object declared with a const qualifier in either language. But you can initialize them in either.
I need an example of what you are talking about here. I use C++ and have RAII as well, but I don't see how RAII has anything to do with initializing an array or a POD struct. Nor do I see how preprocessor magic is simpler than the array initialization I posted upthread. That's about as simple as it gets IMO.
Until you can't because it is const or placed in read-only memory, or you'd rather initialize than assign for debugging purposes, style, coding standard, whatever, and then we are right back here. Also, assignment is more verbose than DI, because you always have to prepend the object name before the member.
Whew! I was beginning to think I was getting the shoulder shrug again! :)
Agreed, that is more verbose. In that case, I'd probably skip DI myself. I would point out a couple of differences though.
Using DI, there would be no need to explicitly initialize the id member. That would be default initialized to zero anyway. But, let's leave it as it is and pretend that someone was using struct a as an overlay but needed to swap the position of the first two members id, and some_char to match up with the memory image. Which one breaks if that someone forgets to update the initializer? Not the DI, and that's what I mean by less maintenance risk. It doesn't even need maintenance at all. In the old-fashioned initializer, you probably wouldn't even get a diagnostic because 0 is fine for a char and 'a' is fine for an integer type.
Well I would agree that designated initializers are useful in C, but they are less useful in C++ since we have constructors in C++. Although it certainly wouldn't hurt to re-absorb all the new features from the latest version of C into the latest C++ standard.
I don't agree - there are circumstances when you want to have a constant table. If LOTS of the entries are zero [take for example a table for your own version of "isdigit, where you have to cope with 256 character values, but only 10 have a value other than zero - this is obviously not a very realistic scenario, because there is no reason not to use isdigit - but it makes for an easy example that most of those who can follow this thread will understand without further explanation].
Now that means that you don't have to write a comment next to each of the characters.Code:char isDigitTable[256] =
{
['0'] = 1,
['1'] = 1,
['2'] = 1,
['3'] = 1,
['4'] = 1,
['5'] = 1,
['6'] = 1,
['7'] = 1,
['8'] = 1,
['9'] = 1,
};
The compiler will do the same as a long lost of zeros [48 of them, to be precise, asssuming we are using ASCII-based character set [1] ] with 10 ones on the end [we don't need to fill in the next 190-odd characters with zero, since that is the default for initialized arrays anyways].
[1] And if we are compiling on a non-ASCII based character set, then the compiler will support the correct digits in whatever character set is being used [assuming the compiler itself understands the character set, that is].
--
Mats
I'm all for DI. I fail to see how constructors can do everything they can. Constructors are better used to default initialize objects (and what if you want to specially initialize only a specific subset of objects inside an array, just like in mats's example?).
I didn't know DI worked with arrays. Yes, for those they are definitely useful and there's no suitable equivalent in C++.
>_<
I don't know if this is a waste of time or not, but I am trying to be polite. Well, at least in this particular post...
I'm not ignoring the discussion whoie. I really did type a rather lengthy, and hopefully understandable, post and followed by a C macro example.
Unfortunately, I was also downloading an ISO and my browser crashed.
So... yea... not typing it all in again, but the short story: the designated initializers as provided by C99 fit to small a niche compared to what C++ provides by implicit partial construction and implicit destruction.
Soma *grumble*
I _HATE_ it when that happens.
I don't think there is any argument on that side - there are all sorts of things we can do in constructor/destructor that are practically impossible to do in C [without much messier code at least]. I also do not think one is a replacement for the other - the DI is a much better solution to arrays and structs where only a (small) part of the data needs to be initialized.Quote:
So... yea... not typing it all in again, but the short story: the designated initializers as provided by C99 fit to small a niche compared to what C++ provides by implicit partial construction and implicit destruction.
Soma *grumble*
--
Mats
That does suck, but perhaps I can offer advice.
Using Firefox and the Session Manager add-on, you should be able to recover from lost information if the browser crashes since it saves information on pages and can recover it if the browser crashes.
And as for the download, all I can suggest is a good download manager. GetRight is my favorite.
Well I didn't say DI was useless in C++, I just said it was less useful than in C since C doesn't have constructors.
Plus in C++ most member variables are private since C++ code usually follows proper encapsulation...
I think C++ should always re-synchronize with the latest C standard to pick up the new features, otherwise the 2 languages will start to become more and more incompatible.
...And there would probably be less of a chance for a successor for C.
I will keep hoping for that.
C++ does resynchronize with C in some aspects. However, not with the complex type (there's already a std::complex), not with VLAs (there's already std::vector) and not with DI (no idea why - apparently no one proposed it).
C1x is already being planned.
There's some reasons behind this paper from Stroustrup regarding the proposed Initializer Lists http://www.open-std.org/jtc1/sc22/wg...2006/n2100.pdf (pdf). Although I'm not sure I follow all of the arguments against DI. In any case, with the inclusion of Initialization Lists, DI becomes mostly redundant.
On one note though, I find the DI syntax for initialization of arrays absolutely hateful and it has no place in C++.
As for the issue of C++ and C merging, I don't think Stroustrup ever discusses the issue outside the realm of wishful thinking, neither is that something that takes away his sleep. In fact, on his own website he ends up dismissing the question entirely and addressing instead the need to eliminate incompatibilities between both languages.
There's nothing about the DI part we're discussing here in this paper. It only discusses the semantics of initializer lists with casts in general, without respect for the contents of the initializer list. (Judging by the example the paper gives, these semantics are quite insane.)
I' not going through the paper again. You can read him discussing compatibility to C99 features (DI on this case) somewhere.
The whole other reasons are discussed when talking about the difficulties behind initializer lists.
Ouch. I'm sorry to hear that. I would have liked to read it.
Well, I can only conclude that if it is too hard to type in again, then the macro can't be simpler than the example I posted upthread. I was also ready to break it by adding more and more dimensions. ;) I really wanted to sandbag you with that! (only kidding of course, I'm really just poking you so that you'll get angry and post it :D)
I would also echo matsp's opinion that one is not really a good replacement for the other. There is no competition here, one is clearly superior over another depending on the circumstance. Constructors for the most part, but DI for arrays and POD structs when it makes sense. Sometimes I don't want a constructor or a destructor, because they don't make any sense for the object or they are even a waste of my time. Sparse lookup tables are a perfect example of that. Some structures for interfacing with a C library or C based API are another.
Hateful? Moreso than the array initializer's that C++ has right now? I doubt it. Perhaps DI isn't going to be accepted by the snobs, but I could care less. It's useful and it's a win-win IMO.
I searched through that doc for 'designated initializers' with no hits, the word 'designated' doesn't even appear in the document. And if you consider that DI is redundant because of the inclusion of initialization lists, then I have to believe you don't understand what it even is. All I saw in the examples in that document were initializers like {1,2,3.14}. Don't get me wrong, C++ needs a solution for initialization lists, but that's the step before DI. Not a replacement for it.
Well, searching for "designated initializers" in a document about "initializer lists" is not going to help you. But actually reading the document will because the issue is implicit on some parts of the discussion when he mentions some of the difficulties in implementing "initializer lists".
I'm not against the inclusion of DI, but I'm not in favor either. I guess I'd give it the same shrug you've seen from others you mentioned. However the syntax in C is unlike anything we have in C++, so that definitely is a point against. If I'm snob because I would like for the programming language syntax to remain coherent, so be it. A big part of the text on top is in fact the discussion of syntactic issues to do with Initializer Lists, so you can see i'm not the only one.
I'll take your word for it. Again, it's the step before, and I would have read it if it applied directly to this particular point. I'll get around to it eventually.
I guess that's a promotion from hateful, so I guess that's good.
*shrug* "Syntax is a secondary issue, and it appears that programmers can learn to love absolutely any syntax." I wonder who said that? Must've been the other Bjarne.
Do me a favor and don't play word games with me. I'll never be in the mood, son. The C DI syntax is hateful, yes. That's my opinion. You want to argue that with actual arguments, shoot. Give me one reason why that syntax makes sense in anything C++. To me it even looks like it was hammered down onto C syntax with a bent nail and a rock for hammer.
Just stop with the "snob", other superlatives, and word games.
quote]*shrug* "Syntax is a secondary issue, and it appears that programmers can learn to love absolutely any syntax." [/quote]
In a way yes. I like Python syntax for instance... and even C++ syntax, go figure -- something so many people despise. But I don't like it when one language syntax is all over the place ruining my carpet. So I wouldn't agree syntax is secondary.
A lot of effort has always been put by the Committee in matters of syntax with respect to new additions to the language and changes to the existing features. Consistency has always been the major goal. You can read it in about any paper dealing with these changes now and in the past. So it has nothing of secondary.
You can however disagree with my opinion on that syntax having no place in C++. That makes a lot more sense than dismissing the whole level of expression of a programming language to a "secondary issue"
All this time, I thought initializing arrays and structures WERE something C++. I simply don't understand your perspective. Why isn't it C++? From what I see, you seem to be saying that:
And I fail to see what is so "Not C++" about that.Code:// C++
const int a[] = {0,0,0,0,0,0,3,0,0,0,0,42,0,0,0,0};
// Not C++
const int a[16] = { [6] = 3, [11] = 42 };
// used like
yz_bucket = a[pulse_prefix & 0xFu];
I'll stop, but hating something useful and productive just because it "isn't C++" is being that which I shall not speak of. If C++ has changed its design goals, then perhaps you are right, it isn't C++ anymore. But one of the goals was so that a programmer wouldn't want to "drop down" to C because it offered something C++ didn't. DI isn't strictly necessary, I agree with that, but it is very useful. If I am writing a decoder of some sort, non-volatile lookup tables become very central to the program. In those types of applications, DI can be a huge bonus. Is C++ supposed to be a language for systems programming, or not?Quote:
Just stop with the "snob", other superlatives, and word games.
Maybe part of the reason why so many C++ programmers couldn't care one way or the other about DI is because it's not something that every programmer will actually use. I'm not sure what type of programming you do (probably very low level), but whatever it is, it sounds like DI is something that you would use quite often. On the other hand, I don't usually do really low level system programming, so I don't think I've ever had a need for DI.
Another point against adding DI to C++ that I can think of is that it just adds one more piece of syntax that C++ developers would need to learn; either that or they'd be scratching their heads if and when they ever encountered it in someone's code.
Well, a few arguments of my own:Quote:
// C++
And I fail to see what is so "Not C++" about that.Code:const int a[] = {0,0,0,0,0,0,3,0,0,0,0,42,0,0,0,0};
// Not C++
const int a[16] = { [6] = 3, [11] = 42 };
- DI syntax is alien to C++. A bracket pair inside an initialization list is novelty and I'm unsure of the complications this can have with the proposed changes to the initialization of sequential containers with initialization lists in C++0x. But being a novely is not necessarily bad (personally as I said before I particularly dislike the syntax. But that's me), if the advantages are important to justify such an inclusion. But there's also...
- The validity of the second definition is questionable under C++ current array initialization rules of its elements. A 0-initialized element under these rules is only possible to the right of the last initializer. I'm unsure of the consequences of changing this rule to now allow 0-initialized elements in the middle of the array. Oddly enough, DI doesn't offer the possibility of specifying a range of elements, consequentely the burden is all on C++ to change its array initialization rules with possible backward compatibilty consequences(?)
- DI lack of breath seems to me a big point against its adoption in C++. It only offers any help to 0-initialized arrays as you describe. If 1 is needed instead of 0, DI can't do a thing. It's useful on some circumstances, but not useful on many.
EDIT: Meanwhile there's nothing stopping you from using DI in a C++ program as we speak.
Why would there be consequences?Quote:
A 0-initialized element under these rules is only possible to the right of the last initializer. I'm unsure of the consequences of changing this rule to now allow 0-initialized elements in the middle of the array.
How about lack of compiler support?Quote:
Meanwhile there's nothing stopping you from using DI in a C++ program as we speak.
Anyway, I think the most important argument against DI in C++ is that there's no way to reasonably represent it in the new initializer list functionality. So again there would be an imbalance in the capabilities in initializers of simple and complex types.
Sure. If your compiler doesn't support C99.
Yes, i did mention this point. You just decided to say it anyway.Quote:
Anyway, I think the most important argument against DI in C++ is that there's no way to reasonably represent it in the new initializer list functionality.
Or doesn't support all C99 features in C++. For example, GCC uses different parsers for C++ and C - it wouldn't be unreasonable at all if DI didn't work in C++, even though the C compiler supports it.Quote:
Sure. If your compiler doesn't support C99.
Not if I'm reading this correctly:
Case handled, AFAICT. Also, initializer_list is just going to be resolved to a built-in array, at least in concept. There is no conflict with DI here:Quote:
We propose to retain the slightly more restrictive rule “never use aggregate initialization
if a constructor is declared”. Without this restriction, we would not be able to enforce
invariants by defining constructors. Consequently, we consider this restriction necessary
and get this modified basic rule:
- If a constructor is declared
- Look for a sequence constructor and use it if we find a best one; if not
- Look for a constructor (excluding sequence constructors) and use it if we find a best one;
- if not, It’s an error
- If no constructor is declared
- look to see if we can do traditional aggregate or built-in type initialization;
- if not, It’s an error
From that paper Mario posted upthread, I see nothing there that would be a good argument against designated initializers. Also, after reading the document, I understand where the hatred comes from. The document compares C99's Compound Literals, NOT designated initializers. Mario, again, you are confusing two different things here.Quote:
Consider:
std::vector<double> v = {1, 2, 3.14};
That’s easily done: std::vector has no sequence constructor (until we add the one
above), so we try {1, 2, 3.14} as a set of arguments to other constructors, that is, we try
vector(1,2,3.14). That fails, so all of the examples fail to compile when X is std::vector.
Now add vector(initializer_list<E>) to vector<E> as shown above. Now, the example
works. The initializer list {1, 2, 3.14} is interpreted as a temporary constructed like this:
That is, the compiler constructs an array containing the initializers converted to theCode:double temp[] = {double(1), double(2), 3.14 } ;
initializer_list<double> tmp(temp,sizeof(temp)/sizeof(double));
vector<double> v(tmp);
desired type (here, double). This array is passed to vector’s sequence constructor as an
initializer_list. The sequence constructor then copies the values from the array into its
own data structure for elements.
Indeed not. My g++ chokes on them, but gcc does not if it isn't in C90 mode. If anyone is still reading this thread, try plugging this through a C99 compiler and a C++ compiler to see if it goes through (avoid the obligatory C criticisms please):
I'd like to hear about anyone who has a C++ compiler that can compile that successfully.Code:whoie$ cat day.c
#include <stdio.h>
#include <time.h>
int main(void) {
puts("Enter a date as mm/dd/yyyy");
int month = 0, day = 0, year = 0;
if ( scanf("%d/%d/%d", &month, &day, &year) != 3 ) return 1;
struct tm timeinfo = {
.tm_year = year - 1900,
.tm_mon = month - 1,
.tm_mday = day
};
mktime(&timeinfo);
char day_name[10] = "";
strftime(day_name, sizeof day_name, "%A", &timeinfo);
printf("That's a %s.\n", day_name);
return 0;
}
whoie$ g++ -o day -W -Wall day.c
day.c: In function 'int main()':
day.c:10: error: expected primary-expression before '.' token
day.c:11: error: expected primary-expression before '.' token
day.c:12: error: expected primary-expression before '.' token
day.c:13: warning: missing initializer for member 'tm::tm_mday'
day.c:13: warning: missing initializer for member 'tm::tm_mon'
day.c:13: warning: missing initializer for member 'tm::tm_year'
day.c:13: warning: missing initializer for member 'tm::tm_wday'
day.c:13: warning: missing initializer for member 'tm::tm_yday'
day.c:13: warning: missing initializer for member 'tm::tm_isdst'
day.c:13: warning: missing initializer for member 'tm::tm_gmtoff'
day.c:13: warning: missing initializer for member 'tm::tm_zone'
whoie$ gcc -o day -std=c99 -W -Wall day.c
whoie$ ./day
Enter a date as mm/dd/yyyy
09/10/2008
That's a Wednesday.
whoie$
Only for types that allow classic aggregate initialization. Which is why I call it an imbalance. The purpose of initializer list support in C++0x is to bring the power of initializer lists to complex types (i.e. those that have constructors). This is not met if at the same time the initializer list is extended in a way that is not compatible with this new support. And there's no way to represent designated initializers in the new initializer_list, no way to map them unto constructor parameters.
The initializer lists with array indices, yes. Not those with field names.Quote:
Also, initializer_list is just going to be resolved to a built-in array, at least in concept. There is no conflict with DI here:
But you are forgetting that there are two cases, one for types with declared constructors, and one without (arrays and POD-structs). Also, the initializer_list proposed appears to only handle homogeneous types. Which takes it completely out of play for structures anyway, because structs can contain heterogeneous types. They are not sequence containers. This is right out of that paper:
I'm unconvinced that the proposed initializer_list would work for that anyway:Quote:
This has of course always worked and it still does. Its meaning is unchanged: initializeCode:struct S { int a; double v; };
S s = { 1, 2.7 };
the members of s in declaration order with the elements from the initializer list in order,
etc.
The template parameter list is only one type.Code:template<class E> class initializer_list {
// representation (a pair of pointers or a pointer plus a length)
public:
constexpr initializer_list(const E*, const E*); // from [first,last)
constexpr initializer_list(const E*, int); // from [first, first+length)
Again, not in play for POD-structures, unless we can discover a way for initializer_list to accept heterogeneous types. According to the proposal:
But they failed to ever show an example of how that would work for heterogeneous lists. The conceptual interim array (see my 2nd to last post upthread) wouldn't work for that. They left a big hole in their proposal by omitting that IMO.Quote:
Initializer lists that are used for aggregates and argument lists can be heterogeneous and need rarely be stored in memory.
No, that's my entire point.Quote:
But you are forgetting that there are two cases, one for types with declared constructors, and one without (arrays and POD-structs).
It doesn't. I'm using initializer_list to refer to all the mechanisms of the protocol. One of those is that this:Quote:
I'm unconvinced that the proposed initializer_list would work for that anyway:
results in a call to the constructor with the three given arguments. In other words, for heterogenous records, the initializer list becomes an alternate syntax for constructor calls. However, there is no way to map the designated initializer's field names onto this mechanism.Code:struct foo
{
foo(int a, float b, std::string c);
};
foo f = {4, 2.3f, "Hello, World!" };
There's no such thing as a heterogenous list in C, and not really in C++.Quote:
But they failed to ever show an example of how that would work for heterogeneous lists.
Nor should there be. That's why there are two cases. One for types with declared constructors (no DI) and one for types without them (DI). No conflict with arrays (as you said before), and no conflict with POD-structs without declared constructors. DI shouldn't be used for types with declared constructors, and won't be if it is adopted straight from C99, so prohibiting their use for types with declared constructors is the right choice. That is a weak argument against DI.
Is that right? {4, 2.3f, "Hello, World!" }? Or are you saying that is not a list in that context or something? I think you knew what I meant.
No, actually based on your objection, I have no clue what you mean.Quote:
I think you knew what I meant.
My argument was that, since the initializer list propsal for C++0x strives to unify types with and without constructors, making the distinction was counterproductive. The types with constructors play catch-up - and the moment they do, DI makes those without go ahead again? Not good for consistency.Quote:
That's why there are two cases.
You agreed that initializer_list and DI would not conflict with each other for array indicies, but you claimed that they would conflict with those having field names. I am arguing that initializer_list can't conflict because it can't be used for heterogeneous lists (like structure initializer lists) anyway. Then you said that there was no such thing as heterogeneous lists, even though you posted an example of one. That is why I got confused about what you were saying.
I understand your objection here, but I am arguing that the solution proposed only really solves the problem for sequence containers. And DI for arrays would fold in naturally there, so one isn't going to go ahead of the other there. Arrays and sequence containers can both use DI for element initilization, because initializer_list will be using a compiler generated interim array anyway. I know you agreed with that already, but I am just trying to point out a distinction that I see.
For the case of structures, DI isn't a move ahead by POD-structs over those with constructors IMO. DI and constructors are not tools that perform the exact same jobs. Constructors set the invariant for the type to true, DI simply provides a better way to initialize members. Certainly, you can use constructors to do the same job as DI, but it is nowhere near as scalable as DI is for that. You would have to create a constructor for every possible permutation of members in order to achieve a general solution. DI can be used for construction if all you do is initialize members, but then you open the very real possibility of violating the type's invariant if there is one. I see DI as bringing a very expressive tool into the language that cannot be replaced by initialzer_list as proposed.
I understand the argument for consistency, and I agree with you that it is important. Even if I agreed that the proposed initializer_list worked out for everything (which I don't), and gave the language consistency here, I don't think it is as important as the benefits that DI brings to it.
It's the benefits issue that I honestly cannot see... I'd be hard pressed to argue some of the remaining discussion regarding initialization lists as proposed on the new standard. All I can surmise is the apparent difficulty implementing DI at the light of the new model and the issue of inconsistency that can be inferred from the document I linked earlier. If you guys think that is not an issue, or is only a partial issue, very well. I lack the knowledge to discuss it.
But the benefits... hmmm....
What is the real benefit of a solution that addresses one case instance. Do you agree for instance that DI would be more useful if it included a description for ranged set of elements? That it could also include the description for different "default" initialization values? In other words, what can DI do for me if I want to have the following?
I argue: as a feature DI scope is too limited to justify an effort in implementing it in C++ if there is bigger fish to fry. I have to agree with you when you say, at the very least for the sake of compatibility it should be implemented. But it wasn't. No going around that.Code:char foo[12] = {'a', 'a', 'c', 'a', 'a', 'e', 'e', 'e', 'e', 'a', 'a', 'a'};
// or this,
int bar[12] = {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1};
It's not the first, neither will it be the last suffering the same fate. But the Committee thrives mostly from community input. And if community input has been so low that I you don't even hear the issue being openly debated, the whole "this is very useful" argument falls flat on its face.
I would argue that the "one case instance", that is, default initialization to zero, is the most common.
What operator would you use to describe a ranged set of elements though? There is nothing like that now. The closest thing I can think of is something like gcc's range operator which you can use for case statements in switch. e.g., case 0..3: You would have to introduce that operator into the language for ranges. DI for arrays could work with that, but you need the operator first. I agree it would be useful, but it's a different feature. Certainly not an argument against DI.
What would the description for different "default" initialization values look like?
My argument is that designated initializers make the language more expressive for initialization of large or complex data structures like structures and arrays. Even better, think of an array of structures containing arrays. Or how about a message catalog mapped to an enumeration of string id's for internationalization (something I had to do very recently). I have already suggested other reasons why I think it's a benefit, and I haven't seen a good argument yet for their exclusion.
Not a great deal, of course. However, I think a string literal would be a better initialization technique for the first, and DI actually could be used for the second. These arrays are too short to see much of a benefit, but the second case could be rewritten like this using one of the properties of DI:
...which is hardly earth-shattering, but the element receives it's last specified initializer using DI. No need to count to see if it is correct, you can tell just by looking at it. Again, not tremendously helpful here, I agree, but consider tables like these:Code:int bar[12] = {
// default initialize the array
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
// override defaults for specific elements
[3] = 0, [4] = 0, [5] = 0
};
Are they equivalent? Do they meet the "spec", and which one is easier to tell? Which is less tedious to work with?Code:int bar[256] = { int bar[256] = {
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,11,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,5,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
[39] = 11, [66] = 5, [174] = 8 };
};