[result_of] Test fails on clang trunk and gcc-4.7 due to changes in FDIS

In the code below, const int f(); decltype(f()) i = 0; `i` has type `int` (not `const int`) in C++11. This is because `f()` is a prvalue of a non-class type (i.e. `const int`) and so its cv qualifiers are ignored. C++0x drafts (before FDIS) had a special rule for function calls in decltype: if e is a function call or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function; but this was removed in FDIS. Clang-3.1 (which will be clang-3.1) and gcc-4.7 seem to have implemented this change, and this change breaks the test case (libs/utility/test/result_of_test.cpp) on those compilers in a C++11 mode. The following are the errors messages: [1] result_of_test.cpp:210:3: error: static assertion failed: (is_same<result_of<const result_of_member_function_template(double)>::type, const double>::value) [2] result_of_test.cpp:211:3: error: static assertion failed: (is_same<result_of<volatile result_of_member_function_template(double)>::type, volatile double>::value) [3] result_of_test.cpp:212:3: error: static assertion failed: (is_same<result_of<const volatile result_of_member_function_template(double)>::type, const volatile double>::value) [4] result_of_test.cpp:239:3: error: static assertion failed: (is_same<result_of<const volatile no_result_type_or_result_of(void)>::type, const unsigned short>::value) [5] result_of_test.cpp:244:3: error: static assertion failed: (is_same<result_of<const volatile no_result_type_or_result_of_template<void>(void)>::type, const unsigned short>::value) Regards, Michel

On 3/28/2012 4:39 AM, Michel Morin wrote:
In the code below,
const int f(); decltype(f()) i = 0;
`i` has type `int` (not `const int`) in C++11. This is because `f()` is a prvalue of a non-class type (i.e. `const int`) and so its cv qualifiers are ignored.
C++0x drafts (before FDIS) had a special rule for function calls in decltype: if e is a function call or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function; but this was removed in FDIS. <snip>
That wording should still be FDIS. That's decltype v1.1 that Stephan was referring to in the other result_of thread you've discussed. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 3/28/2012 9:09 AM, Eric Niebler wrote:
On 3/28/2012 4:39 AM, Michel Morin wrote:
In the code below,
const int f(); decltype(f()) i = 0;
`i` has type `int` (not `const int`) in C++11. This is because `f()` is a prvalue of a non-class type (i.e. `const int`) and so its cv qualifiers are ignored.
C++0x drafts (before FDIS) had a special rule for function calls in decltype: if e is a function call or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function; but this was removed in FDIS. <snip>
That wording should still be FDIS. That's decltype v1.1 that Stephan was referring to in the other result_of thread you've discussed.
Unless I'm mistaken, the FDIS is N3290, and the wording is there. I have it in front of me. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote
On 3/28/2012 9:09 AM, Eric Niebler wrote:
On 3/28/2012 4:39 AM, Michel Morin wrote:
In the code below,
const int f(); decltype(f()) i = 0;
`i` has type `int` (not `const int`) in C++11. This is because `f()` is a prvalue of a non-class type (i.e. `const int`) and so its cv qualifiers are ignored.
C++0x drafts (before FDIS) had a special rule for function calls in decltype: if e is a function call or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function; but this was removed in FDIS. <snip>
That wording should still be FDIS. That's decltype v1.1 that Stephan was referring to in the other result_of thread you've discussed.
Unless I'm mistaken, the FDIS is N3290, and the wording is there. I have it in front of me.
Hmm…, my N3290 does not have such a wording in 7.1.6.2 (dcl.type.simple) p4. In N3291 (FDIS with diff), the wording is explicitly crossed out. Am I missing something? Regards, Michel

On 3/28/2012 1:19 PM, Michel Morin wrote:
Eric Niebler wrote
On 3/28/2012 9:09 AM, Eric Niebler wrote:
On 3/28/2012 4:39 AM, Michel Morin wrote:
In the code below,
const int f(); decltype(f()) i = 0;
`i` has type `int` (not `const int`) in C++11. This is because `f()` is a prvalue of a non-class type (i.e. `const int`) and so its cv qualifiers are ignored.
C++0x drafts (before FDIS) had a special rule for function calls in decltype: if e is a function call or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function; but this was removed in FDIS. <snip>
That wording should still be FDIS. That's decltype v1.1 that Stephan was referring to in the other result_of thread you've discussed.
Unless I'm mistaken, the FDIS is N3290, and the wording is there. I have it in front of me.
Hmm…, my N3290 does not have such a wording in 7.1.6.2 (dcl.type.simple) p4.
The (non-normative) note in 7.1.6.2 about this is in p5, not p4. But the normative text is in 5.2.2 p11.
In N3291 (FDIS with diff), the wording is explicitly crossed out. Am I missing something?
OK, looking at N3291 now. First, I see the date of this paper is earlier than N3290. Don't be misled by the fact that it has a higher N number. It's possible Pete requested a number from Clark for the FDIS before he asked for a number for the last working draft. Regardless, I don't see the new text as crossed out. I see it in blue and underlined to highlight the fact that it's new. Specifically, I'm looking at 5.2.2 p11 and 7.1.6.2 p4. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Hmm…, my N3290 does not have such a wording in 7.1.6.2 (dcl.type.simple) p4.
The (non-normative) note in 7.1.6.2 about this is in p5, not p4. But the normative text is in 5.2.2 p11.
I don't see any text about about how decltype of a function call expression is determined in 5.2.2 p11 or 7.1.6.2 p5. Sorry, my post may be misleading and not clear. The subject of this thread should be: "Test fails on clang trunk and gcc-4.7 due to changes *made* in FDIS" and I'm talking about the changes *made* in FDIS. Specifically, the change is about how decltype of a function call expression is determined. * N3242 says that in 7.1.6.2 p4: if e is a function call or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function; * N3290 (FDIS) does not have such a wording. For a function call expression, decltype(e) is determined by the last rule in 7.1.6.2 p4: otherwise, decltype(e) is the type of e. So, for "const int f();", * In N3242, decltype(f()) is const int; * In N3290, decltype(f()) is int. Regards, Michel

On 3/28/2012 2:58 PM, Michel Morin wrote:
Eric Niebler wrote:
Hmm…, my N3290 does not have such a wording in 7.1.6.2 (dcl.type.simple) p4.
The (non-normative) note in 7.1.6.2 about this is in p5, not p4. But the normative text is in 5.2.2 p11.
I don't see any text about about how decltype of a function call expression is determined in 5.2.2 p11 or 7.1.6.2 p5.
Sorry, my post may be misleading and not clear. The subject of this thread should be: "Test fails on clang trunk and gcc-4.7 due to changes *made* in FDIS" and I'm talking about the changes *made* in FDIS.
OK.
Specifically, the change is about how decltype of a function call expression is determined. * N3242 says that in 7.1.6.2 p4: if e is a function call or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function;
* N3290 (FDIS) does not have such a wording. For a function call expression, decltype(e) is determined by the last rule in 7.1.6.2 p4: otherwise, decltype(e) is the type of e.
So, for "const int f();", * In N3242, decltype(f()) is const int; * In N3290, decltype(f()) is int.
Ah. *Now* I see what you're saying. <palmface> I think I agree with your analysis, but I'm going to check with somebody real quick. It's funny, I don't remember this change being discussed as part of the decltype 1.1 discussion. It was probably changed at the very last pre-FDIS committee meeting, which I didn't attend. Stay tuned ... -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 3/28/2012 3:42 PM, Eric Niebler wrote:
On 3/28/2012 2:58 PM, Michel Morin wrote:
Specifically, the change is about how decltype of a function call expression is determined. * N3242 says that in 7.1.6.2 p4: if e is a function call or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function;
* N3290 (FDIS) does not have such a wording. For a function call expression, decltype(e) is determined by the last rule in 7.1.6.2 p4: otherwise, decltype(e) is the type of e.
Right. I spoke with James Widman about this. He says the change was not because of the decltype v1.1 change, but rather about fixing core core issue 1212: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3368.html#1212
So, for "const int f();", * In N3242, decltype(f()) is const int; * In N3290, decltype(f()) is int.
Ah. *Now* I see what you're saying. <palmface> I think I agree with your analysis, but I'm going to check with somebody real quick. It's funny, I don't remember this change being discussed as part of the decltype 1.1 discussion. It was probably changed at the very last pre-FDIS committee meeting, which I didn't attend.
Stay tuned ...
James Widman also agrees with your analysis. I guess the result_of tests are wrong then. Could you file a bug? -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Specifically, the change is about how decltype of a function call expression is determined. * N3242 says that in 7.1.6.2 p4: if e is a function call or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function;
* N3290 (FDIS) does not have such a wording. For a function call expression, decltype(e) is determined by the last rule in 7.1.6.2 p4: otherwise, decltype(e) is the type of e.
Right. I spoke with James Widman about this. He says the change was not because of the decltype v1.1 change, but rather about fixing core core issue 1212:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3368.html#1212
Thanks for providing the information! I understand why the rule for xvalues is added, but I don't understand why the rule for function calls is removed. This removal is a breaking change... [snip]
James Widman also agrees with your analysis. I guess the result_of tests are wrong then.
To accommodate both N3290 (FDIS) decltype and pre-N3290 decltype, we need to modify the failed tests to something like this: typedef const int F(); BOOST_STATIC_ASSERT((is_same< remove_const<result_of<F&()>::type>::type , int >::value)); Or, should decltype-based boost::result_of emulate N3290 decltype even on a compiler with pre-N3290 decltype? Also, the implementation needs to be modified. The current implementation of decltype-based boost::result_of does not use decltype for function pointers. So, for "typedef const int F();" * boost::result_of<F&()>::type is int, * boost::result_of<F*()>::type is const int, on a compiler with N3290 decltype.
Could you file a bug?
OK, I will file a bug later. Regards, Michel

Michel Morin wrote:
Could you file a bug?
OK, I will file a bug later.
Done. https://svn.boost.org/trac/boost/ticket/6754
Also, the implementation needs to be modified. The current implementation of decltype-based boost::result_of does not use decltype for function pointers. So, for "typedef const int F();" * boost::result_of<F&()>::type is int, * boost::result_of<F*()>::type is const int, on a compiler with N3290 decltype.
I also created a ticket for this. A patch attached in the ticket. https://svn.boost.org/trac/boost/ticket/6755 Regards, Michel

On Mar 31, 2012, at 11:36 PM, Michel Morin wrote:
Also, the implementation needs to be modified. The current implementation of decltype-based boost::result_of does not use decltype for function pointers. So, for "typedef const int F();" * boost::result_of<F&()>::type is int, * boost::result_of<F*()>::type is const int, on a compiler with N3290 decltype.
I also created a ticket for this. A patch attached in the ticket. https://svn.boost.org/trac/boost/ticket/6755
Applied and fixed. Thanks! - Daniel
participants (3)
-
Daniel Walker
-
Eric Niebler
-
Michel Morin