|  | arrays and cv qualification conversions |  | |
| | | Christof Meerwald |  |
| Posted: Sat Sep 06, 2008 8:24 pm Post subject: arrays and cv qualification conversions |  |
Hi,
consider the following program:
void f1(char *a[][2]) { }
void f2(char * const a[][2]) { }
void f3(const char * const a[][2]) { }
int main() { char *a[1][2];
f1(a); f2(a); f3(a); }
which of these function calls (conversions) are legal?
Most compilers appear to be happy with f2 (g++ 4.2, Visual C++ 2008, Sun Studio 12, Digital Mars C++, HP aCC), but only Digital Mars and Sun Studio will accept f3.
Can anyone point me to the section in the C++ standard where it allows these conversions?
Christof
-- LINK sip:cmeerw at cmeerw.org mailto:cmeerw at cmeerw.org xmpp:cmeerw at cmeerw.org
[ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Jiang |  |
| Posted: Tue Sep 09, 2008 11:58 am Post subject: Re: arrays and cv qualification conversions |  |
| |  | |
On Sep 7, 5:24 am, Christof Meerwald <NOSPAM-seeMySig +ue...@usenet.cmeerw.org> wrote:
Understand the argument types help here in my mind.
| Quote: | consider the following program:
void f1(char *a[][2]) { }
|
f1's argument type
a is array of an 2-elements-array, and the elements are pointer to char
Here the first bound const is omitted, which means, the first dimension is free.
| Quote: | void f2(char * const a[][2]) { }
|
f2's argument type
a is array of an 2-elements-array, and the elements are const pointer to char
Note here the "const" is applied to the array, further applied to the elements of the array. See 3.9.3/p5 for details.
| Quote: | void f3(const char * const a[][2]) { }
|
f3's argument type
a is array of an 2-elements-array, and the elements are const pointer to const char
Now let's see your array definition and function calls.
| Quote: | int main() { char *a[1][2];
|
You defined an array, and the type
a is an array with only 1 element, and the element is array of 2 pointer to char
Legal function call.
compiler can do the exact match using array-pointer conversion.
Again, legal function call.
Although you did not provide the const specifier in your array definition, the compiler can will use qualification conversion for resolution defined in 13.3.3. This is also a exact match.
For qualification conversion(4.4), it is required that an rvalue of type "pointer to cv1 T" can be converted to an rvalue of type "pointer to cv2 T" if "cv2 T" is more cv-qualified than "cv1 T". For your example, cv1 is "no cv-qualifier" and cv2 is "const", therefore we see the conversion is reasonable according to 3.9.3/p4.
Well, the compiler will have trouble dealing with this beast. Actually this call is illegal.
f3 requires both the array (underlying elements) and the *contents*, pointed by the element pointers, should be const. In 13.3.3, we do not have any valid conversion defined to do that. More specifically, qualification conversion can not applied recursively for "layered indirections".
| Quote: | }
which of these function calls (conversions) are legal?
|
f1 and f2.
f3 is ill-formed.
| Quote: | Most compilers appear to be happy with f2 (g++ 4.2, Visual C++ 2008, Sun Studio 12, Digital Mars C++, HP aCC), but only Digital Mars and Sun Studio will accept f3.
Can anyone point me to the section in the C++ standard where it allows these conversions?
|
For f1 and f2, see my above explanation, the diagnostic for f3 can be induced from these rules in my mind.
Regards,
Jiang
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Christof Meerwald |  |
| Posted: Tue Sep 09, 2008 10:10 pm Post subject: Re: arrays and cv qualification conversions |  |
| |  | |
On Tue, 9 Sep 2008 05:58:49 CST, Jiang wrote:
| Quote: | On Sep 7, 5:24 am, Christof Meerwald <NOSPAM-seeMySig +ue...@usenet.cmeerw.org> wrote: Understand the argument types help here in my mind.
|
While I don't necessarily agree with every part of your explanation (as I don't see why overload resolution would be relevant here), I think I got the idea. I think it becomes much more obvious when introducing a typedef for the array:
typedef char *Array[2];
| Quote: | void f1(char *a[][2])
|
this would then be equivalent to:
void f1(Array *a)
| Quote: | void f2(char * const a[][2])
|
and (because a const qualifier for the array applies to the element type) this is equivalent to:
void f2(const Array *a)
and then it's obvious that "Array *" can be converted to "const Array *".
Christof
-- LINK sip:cmeerw at cmeerw.org mailto:cmeerw at cmeerw.org xmpp:cmeerw at cmeerw.org
[ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Jiang |  |
| Posted: Thu Sep 11, 2008 5:04 am Post subject: Re: arrays and cv qualification conversions |  |
| |  | |
On Sep 10, 7:10 am, Christof Meerwald <NOSPAM-seeMySig +uz...@usenet.cmeerw.org> wrote:
| Quote: | On Tue, 9 Sep 2008 05:58:49 CST, Jiang wrote: On Sep 7, 5:24 am, Christof Meerwald <NOSPAM-seeMySig +ue...@usenet.cmeerw.org> wrote: Understand the argument types help here in my mind.
While I don't necessarily agree with every part of your explanation (as I don't see why overload resolution would be relevant here),
|
Same here. :-(
I don't know why I quoted rules for overloading in my previous late- night post. Seems I should go to bed instead of post here in the late night.
For your example, standard conversions only will be enough and I apologize for the confusion I've made.
| Quote: | I think I got the idea. I think it becomes much more obvious when introducing a typedef for the array:
typedef char *Array[2];
|
Which is true in my mind.
A short summary for your question:
1. f1 is legal because using array-to-pointer conversion.
2. Because we have another standard conversion, qualification conversion, therefore f2 is also well-formed.
3. f3 is not legal because we can not find exact match and necessary standard conversions to make it legal.
and,
4. Using typedef for multi-level declaration is sometimes useful. (but we still must be careful where the const specifiers are)
Regards,
Jiang
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | blargg |  |
| Posted: Sat Sep 13, 2008 8:32 pm Post subject: Re: arrays and cv qualification conversions |  |
| |  | |
In article <slrngc50ef.jqv.NOSPAM-seeMySig@msgid.cmeerw.org>, Christof Meerwald <NOSPAM-seeMySig+ue45+@usenet.cmeerw.org> wrote:
| Quote: | consider the following program: [shortened] void f1(char *a[][2]); void f2(char * const a[][2]); void f3(const char * const a[][2]);
int main() { char *a[1][2];
f1(a); f2(a); f3(a); }
which of these function calls (conversions) are legal?
Most compilers appear to be happy with f2 (g++ 4.2, Visual C++ 2008, Sun Studio 12, Digital Mars C++, HP aCC), but only Digital Mars and Sun Studio will accept f3.
Can anyone point me to the section in the C++ standard where it allows these conversions?
|
First, let's eliminate the implicit array-to-pointer nonsense, since that's not at the heart of your question:
void f1(char * (*a)[2]); // pointer to char * [2] void f2(char * const (*a)[2]); // pointer to char * const [2] void f3(const char * const (*a)[2]); // pointer to const char* const [2]
int main() { char* aa [2]; char* (*a) [2] = aa; // pointer to char* [2] f1(a); f2(a); f3(a); }
All three calls are valid as far as I can tell. The first doesn't involve any conversion. The second simply converts from pointer-to-T to pointer-to-const-T, clearly valid. The third is the tricky one, and valid as far as I can tell. See section 4.4 Qualification Conversions, paragraph 4. In summary, you can add const (and volatile) at any "depth", as long as you also add const to all shallower levels. As stated in the standard, this is to ensure that const safety isn't implicitly violated. The reasoning is that when you add it at some level, it's not there in the caller's type therefore if the pointer were changed to point to a const object, the caller could modify it. Therefore, const must be added to all shallower levels to prevent the callee from changing anything. Examining f3(), one can see that there's no way const safety can be violated without a cast. If we added f4()
void f4(const char * (*a)[2]); // pointer to const char* [2]
calling it would be in error, since it could do (*a) [0] = "foo", and then the main(0 could attempt to modify the string's contents by doing (*a) [0] [0] = 'X', all without any const_cast.
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Jiang |  |
| Posted: Sun Sep 14, 2008 5:30 pm Post subject: Re: arrays and cv qualification conversions |  |
| |  | |
On Sep 14, 5:32 am, blargg <blargg....@gishpuppy.com> wrote:
| Quote: | In article <slrngc50ef.jqv.NOSPAM-seeMy...@msgid.cmeerw.org>, Christof Meerwald <NOSPAM-seeMySig+ue...@usenet.cmeerw.org> wrote:
consider the following program: [shortened] void f1(char *a[][2]); void f2(char * const a[][2]); void f3(const char * const a[][2]);
int main() { char *a[1][2];
f1(a); f2(a); f3(a); }
which of these function calls (conversions) are legal?
Most compilers appear to be happy with f2 (g++ 4.2, Visual C++ 2008, Sun Studio 12, Digital Mars C++, HP aCC), but only Digital Mars and Sun Studio will accept f3.
Can anyone point me to the section in the C++ standard where it allows these conversions?
First, let's eliminate the implicit array-to-pointer nonsense, since that's not at the heart of your question:
|
Huh? why the above conversion is nonsense? Without such a good, old conversion, none of the OP's function calls is valid.
Please note rules are rules, there are no so-called first-class rules or second-class rules. If you feel some rules are special, then the only thing I can see is, well, you are not familiar with them.
-> Actually your example code proves my words. :-)
| Quote: | void f1(char * (*a)[2]); // pointer to char * [2] void f2(char * const (*a)[2]); // pointer to char * const [2] void f3(const char * const (*a)[2]); // pointer to const char* const [2]
int main() { char* aa [2]; char* (*a) [2] = aa; // pointer to char* [2]
|
[...]
1. The above code/conversion is ill-formed. Ask here if you can not find the reason.
2. Compared with the OP's question, your example has different semantics and also I do not find how your explanation contributes on the better understanding for this topic.
Regards,
Jiang
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | blargg |  |
| Posted: Mon Sep 15, 2008 2:51 am Post subject: Re: arrays and cv qualification conversions |  |
| |  | |
In article <ce6f32c9-fb11-478f-8e69-5ac0442a1cca@a8g2000prf.googlegroups.com>, Jiang <goo.mail01@yahoo.com> wrote:
| Quote: | On Sep 14, 5:32 am, blargg <blargg....@gishpuppy.com> wrote: In article <slrngc50ef.jqv.NOSPAM-seeMy...@msgid.cmeerw.org>, Christof Meerwald <NOSPAM-seeMySig+ue...@usenet.cmeerw.org> wrote: consider the following program: [shortened] void f1(char *a[][2]); void f2(char * const a[][2]); void f3(const char * const a[][2]); int main() { char *a[1][2];
f1(a); f2(a); f3(a); } [...] First, let's eliminate the implicit array-to-pointer nonsense, since that's not at the heart of your question:
Huh? why the above conversion is nonsense? Without such a good, old conversion, none of the OP's function calls is valid.
|
I meant the fact that
void f1(char *a[][2]);
is treated by the compiler as if it were
void f1(char *(*a)[2]);
I don't think this equivalence was at the heart of the original poster's question, so I rewrote the functions to just say directly what they were really taking. I also was removing the array-to-pointer-to-first-element conversion that was occurring elsewhere, since that was also complicating matters. I understood the poster to be asking about the differing const usage in the three functions, and whether some or all were valid, and why.
| Quote: | Please note rules are rules, there are no so-called first-class rules or second-class rules. If you feel some rules are special, then the only thing I can see is, well, you are not familiar with them.
|
I have no idea what you're talking about here. Where did I mention first-class and second-class rules in my message? Are you referring to the fact that I started my message with "First,"?
| Quote: | -> Actually your example code proves my words. 
|
Proves what? I'm not following what you mean. And why the condescension? I don't think it's warranted.
| Quote: | void f1(char * (*a)[2]); // pointer to char * [2] void f2(char * const (*a)[2]); // pointer to char * const [2] void f3(const char * const (*a)[2]); // pointer to const char* const [2]
int main() { char* aa [2]; char* (*a) [2] = aa; // pointer to char* [2] [...] 1. The above code/conversion is ill-formed. Ask here if you can not find the reason.
|
OK, I left out & before aa. The point of the example was the calls to f1, f2, and f3.
| Quote: | 2. Compared with the OP's question, your example has different semantics and also I do not find how your explanation contributes on the better understanding for this topic.
|
The only other difference is that I made 'a' in main() a pointer to char* [2], which is what it was decaying to anyway when passed to any of the functions. I felt it was clearer to remove the implicit array-to-pointer conversion, since that seemed irrelevant to the const issue. Perhaps you're saying that this implicit conversion was making section 4.4 not even apply?
Are we at least in agreement of the following lines?
char** p = 0;
char * const* p2 = p; // OK char const* const* p3 = p; // OK char const* * p4 = p; // error
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
|
|