[result_of] fails with clan (C++11)

Hello, clang (c++11 support) fails on code like: BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type >::value)); with error: no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type >::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~ ../boost/static_assert.hpp:48:50: note: expanded from macro 'BOOST_STATIC_ASSERT' # define BOOST_STATIC_ASSERT( B ) static_assert(B, #B) ^ Do you know why it fails? (other compilers like gcc, intel, msvc compile the code) regards, Oliver

On Tue, Nov 27, 2012 at 12:47 PM, Oliver Kowalke <oliver.kowalke@gmail.com>wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type >::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type >::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type? There might've been a recent change only for Clang to allow result_of to be better usable with SFINAE: result_of< F ( Args... ) > doesn't have a nested type typedef if F ( Args... ) is ill-formed (which appears to be the case here). ../boost/static_assert.hpp:48:**50: note: expanded from macro
'BOOST_STATIC_ASSERT' # define BOOST_STATIC_ASSERT( B ) static_assert(B, #B) ^
Do you know why it fails? (other compilers like gcc, intel, msvc compile the code)
- Jeff

On 27/11/12 21:56, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Nov 27, 2012 at 12:47 PM, Oliver Kowalke <oliver.kowalke@gmail.com>wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type >::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type >::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type?
There might've been a recent change only for Clang to allow result_of to be better usable with SFINAE: result_of< F ( Args... ) > doesn't have a nested type typedef if F ( Args... ) is ill-formed (which appears to be the case here).
And the person who did that change didn't think of running the test?

Mathias Gaunard wrote:
On 27/11/12 21:56, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Nov 27, 2012 at 12:47 PM, Oliver Kowalke <oliver.kowalke@gmail.com>wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type
::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type
::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type?
There might've been a recent change only for Clang to allow result_of to be better usable with SFINAE: result_of< F ( Args... ) > doesn't have a nested type typedef if F ( Args... ) is ill-formed (which appears to be the case here).
And the person who did that change didn't think of running the test?
The test looks broken. A function that takes X& can't be called with zero arguments.

On Tue, Nov 27, 2012 at 1:28 PM, Peter Dimov <lists@pdimov.com> wrote:
Mathias Gaunard wrote:
On 27/11/12 21:56, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Nov 27, 2012 at 12:47 PM, Oliver Kowalke <oliver.kowalke@gmail.com>**wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type >> ::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type >> ::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~****~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function > type?
There might've been a recent change only for Clang to allow result_of to > be better usable with SFINAE: result_of< F ( Args... ) > doesn't have a > nested type typedef if F ( Args... ) is ill-formed (which appears to be the > case here).
And the person who did that change didn't think of running the test?
The test looks broken. A function that takes X& can't be called with zero arguments.
Yes, the assertion looks wrong, though something that would pass with the non-decltype implementation of result_of...which might explain its failure on clang if clang was switched to used decltype? Everything I've said in this thread is speculation, by the way. - Jeff

On 27/11/12 22:21, Mathias Gaunard wrote:
On 27/11/12 21:56, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Nov 27, 2012 at 12:47 PM, Oliver Kowalke <oliver.kowalke@gmail.com>wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type >::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type >::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type?
There might've been a recent change only for Clang to allow result_of to be better usable with SFINAE: result_of< F ( Args... ) > doesn't have a nested type typedef if F ( Args... ) is ill-formed (which appears to be the case here).
And the person who did that change didn't think of running the test?
My bad, I assumed this was a test from Boost, but this doesn't seem to be the case.

On 11/27/2012 2:13 PM, Mathias Gaunard wrote:
On 27/11/12 22:21, Mathias Gaunard wrote:
On 27/11/12 21:56, Jeffrey Lee Hellrung, Jr. wrote:
On Tue, Nov 27, 2012 at 12:47 PM, Oliver Kowalke <oliver.kowalke@gmail.com>wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type
::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type
::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type?
There might've been a recent change only for Clang to allow result_of to be better usable with SFINAE: result_of< F ( Args... ) > doesn't have a nested type typedef if F ( Args... ) is ill-formed (which appears to be the case here).
And the person who did that change didn't think of running the test?
My bad, I assumed this was a test from Boost, but this doesn't seem to be the case.
Right, this isn't a boost test case, and it's wrong in any case. This behavior is by design. The TR1 result_of protocol requires all nullary function signatures (like result_of<Fn()>::type) to be void, regardless of whether the function can actually be called with no arguments or not. The C++11 result_of (with decltype), result_of is supposed to get the right answer always. This was fully documented for the 1.52 release. There is a note in red on the boost.org homepage that takes you here: http://www.boost.org/users/news/a_special_note_for_boost_1_52_0_and_higher.h... And a link there takes you to the full discussion: http://www.boost.org/doc/libs/1_52_0/libs/utility/utility.htm#result_of Please see the section "Known differences between boost::result_of and TR1 result_of", which describes the difference for nullary functions and function objects. Thanks, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type >::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type >::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type?
it's called inside a templated function: template< typename Fn > void g(BOOST_RV_RV( Fn) fn){ BOOST_STATIC_ASSERT(...) ....} in the example it was instantiated with a function pointer void(*)(X&)
There might've been a recent change only for Clang to allow result_of to be better usable with SFINAE: result_of< F ( Args... ) > doesn't have a nested type typedef if F ( Args... ) is ill-formed (which appears to be the case here).
it's strange because clang(version unknown) fails only on MacOSX - on Linux clang (3.2) compiles the same code regards, Oliver
../boost/static_assert.hpp:48:**50: note: expanded from macro
'BOOST_STATIC_ASSERT' # define BOOST_STATIC_ASSERT( B ) static_assert(B, #B) ^
Do you know why it fails? (other compilers like gcc, intel, msvc compile the code)
- Jeff
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 28/11/12 08:42, Oliver Kowalke wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type >::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type >::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type?
it's called inside a templated function: template< typename Fn > void g(BOOST_RV_RV( Fn) fn){ BOOST_STATIC_ASSERT(...) ....}
remove the reference from Fn (at least in C++11). I don't know what the actual type of Fn is in C++03.

On 11/28/2012 6:14 AM, Mathias Gaunard wrote:
On 28/11/12 08:42, Oliver Kowalke wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type
::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type
::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type?
it's called inside a templated function: template< typename Fn > void g(BOOST_RV_RV( Fn) fn){ BOOST_STATIC_ASSERT(...) ....}
remove the reference from Fn (at least in C++11). I don't know what the actual type of Fn is in C++03.
Did my previous answer not fully address this issue? The function type void(&)(X&) cannot be called with 0 arguments, so a decltype-based result_of will have the behavior your observe. The old TR1-style result_of will give you void. At present, decltype-based result_of is only enabled for very recent clang builds. This explains the difference. -- Eric Niebler BoostPro Computing http://www.boostpro.com

would function_traits<Fn>::result_type work better? Am 28.11.2012 19:45 schrieb "Eric Niebler" <eric@boostpro.com>:
On 11/28/2012 6:14 AM, Mathias Gaunard wrote:
On 28/11/12 08:42, Oliver Kowalke wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type
::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type
::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type?
it's called inside a templated function: template< typename Fn > void g(BOOST_RV_RV( Fn) fn){ BOOST_STATIC_ASSERT(...) ....}
remove the reference from Fn (at least in C++11). I don't know what the actual type of Fn is in C++03.
Did my previous answer not fully address this issue? The function type void(&)(X&) cannot be called with 0 arguments, so a decltype-based result_of will have the behavior your observe. The old TR1-style result_of will give you void. At present, decltype-based result_of is only enabled for very recent clang builds. This explains the difference.
-- Eric Niebler BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

(Rearranging ...) On 11/28/2012 11:32 AM, Oliver Kowalke wrote:
Am 28.11.2012 19:45 schrieb "Eric Niebler" <eric@boostpro.com>:
On 11/28/2012 6:14 AM, Mathias Gaunard wrote:
On 28/11/12 08:42, Oliver Kowalke wrote:
Hello, clang (c++11 support) fails on code like:
BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Fn() >::type > ::value));
with error:
no type named 'type' in 'boost::result_of<void (&())(X &)>' is_same< void, typename result_of< Fn() >::type > ::value)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~**~~
Does Fn == void (&)(X&) or void (X&) ? I.e., is it a unary function type?
it's called inside a templated function: template< typename Fn > void g(BOOST_RV_RV( Fn) fn){ BOOST_STATIC_ASSERT(...) ....}
remove the reference from Fn (at least in C++11). I don't know what the actual type of Fn is in C++03.
Did my previous answer not fully address this issue? The function type void(&)(X&) cannot be called with 0 arguments, so a decltype-based result_of will have the behavior your observe. The old TR1-style result_of will give you void. At present, decltype-based result_of is only enabled for very recent clang builds. This explains the difference.
would function_traits<Fn>::result_type work better?
You are asking result_of to compute the result of calling a unary function that takes an X& with zero arguments. That's nonsensical. If you intend to call it with an X&, then ask it what the result is when called with an X&: boost::result_of< Fn(X&) >::type This should correctly report void regardless of whether result_of uses decltype or the TR1 result_of protocol. HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

You are asking result_of to compute the result of calling a unary function that takes an X& with zero arguments. That's nonsensical. If you intend to call it with an X&, then ask it what the result is when called with an X&:
boost::result_of< Fn(X&) >::type
This should correctly report void regardless of whether result_of uses decltype or the TR1 result_of protocol.
OK, I got it. It's strange that clang 3.2 (c++11), gcc, ontel and msvc compile the code without errors on Loinux and Windows.

2012/11/28 Oliver Kowalke <oliver.kowalke@gmail.com>
You are asking result_of to compute the result of calling a unary function that takes an X& with zero arguments. That's nonsensical. If you intend to call it with an X&, then ask it what the result is when called with an X&:
boost::result_of< Fn(X&) >::type
This should correctly report void regardless of whether result_of uses decltype or the TR1 result_of protocol.
OK, I got it. It's strange that clang 3.2 (c++11), gcc, ontel and msvc compile the code without errors on Loinux and Windows.
I thought I could the problem can be solved like the following code, but it does not compile for gcc (c++0x): #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< typename Fn > void g( BOOST_RV_REF( Fn) ) { typedef typename remove_reference< Fn >::type Y; BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Y( X &) >::type >::value)); } #else ... #endif g() should be callable with function pointers, copyable and moveable-only functors (signatue void( X&)). Again - the original code works for gcc, intel, msvc and clang (Linux) and fails for clang on MacOS X.

On Wed, Nov 28, 2012 at 1:25 PM, Oliver Kowalke <oliver.kowalke@gmail.com>wrote:
2012/11/28 Oliver Kowalke <oliver.kowalke@gmail.com>
You are asking result_of to compute the result of calling a unary function that takes an X& with zero arguments. That's nonsensical. If you intend to call it with an X&, then ask it what the result is when called with an X&:
boost::result_of< Fn(X&) >::type
This should correctly report void regardless of whether result_of uses decltype or the TR1 result_of protocol.
OK, I got it. It's strange that clang 3.2 (c++11), gcc, ontel and msvc compile the code without errors on Loinux and Windows.
I thought I could the problem can be solved like the following code, but it does not compile for gcc (c++0x):
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< typename Fn > void g( BOOST_RV_REF( Fn) ) { typedef typename remove_reference< Fn >::type Y; BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Y( X &) >::type >::value)); } #else ... #endif
g() should be callable with function pointers, copyable and moveable-only functors (signatue void( X&)).
Again - the original code works for gcc, intel, msvc and clang (Linux) and fails for clang on MacOS X.
It would help if you gave a complete, compilable example and the error you're getting. - Jeff

regression tests in trunk - boost.coroutine but I've commented out the assertion thx, Oliver Am 29.11.2012 01:32 schrieb "Jeffrey Lee Hellrung, Jr." < jeffrey.hellrung@gmail.com>:
On Wed, Nov 28, 2012 at 1:25 PM, Oliver Kowalke <oliver.kowalke@gmail.com
wrote:
2012/11/28 Oliver Kowalke <oliver.kowalke@gmail.com>
You are asking result_of to compute the result of calling a unary function that takes an X& with zero arguments. That's nonsensical. If you intend to call it with an X&, then ask it what the result is when called with an X&:
boost::result_of< Fn(X&) >::type
This should correctly report void regardless of whether result_of
uses
decltype or the TR1 result_of protocol.
OK, I got it. It's strange that clang 3.2 (c++11), gcc, ontel and msvc compile the code without errors on Loinux and Windows.
I thought I could the problem can be solved like the following code, but it does not compile for gcc (c++0x):
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< typename Fn > void g( BOOST_RV_REF( Fn) ) { typedef typename remove_reference< Fn >::type Y; BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Y( X &) >::type ::value)); } #else ... #endif
g() should be callable with function pointers, copyable and moveable-only functors (signatue void( X&)).
Again - the original code works for gcc, intel, msvc and clang (Linux) and fails for clang on MacOS X.
It would help if you gave a complete, compilable example and the error you're getting.
- Jeff
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 11/28/2012 1:25 PM, Oliver Kowalke wrote:
2012/11/28 Oliver Kowalke <oliver.kowalke@gmail.com>
You are asking result_of to compute the result of calling a unary function that takes an X& with zero arguments. That's nonsensical. If you intend to call it with an X&, then ask it what the result is when called with an X&:
boost::result_of< Fn(X&) >::type
This should correctly report void regardless of whether result_of uses decltype or the TR1 result_of protocol.
OK, I got it. It's strange that clang 3.2 (c++11), gcc, ontel and msvc compile the code without errors on Loinux and Windows.
I've already explained this. Decltype-based result_of is only turned on by default for compilers that have strong-enough decltype support. That is currently only very recent clang versions. That does NOT include gcc, intel or msvc.
I thought I could the problem can be solved like the following code, but it does not compile for gcc (c++0x):
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< typename Fn > void g( BOOST_RV_REF( Fn) ) { typedef typename remove_reference< Fn >::type Y; BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Y( X &) >::type >::value)); } #else ... #endif
If Fn is void(&)(X&), then remove_reference<Fn>::type is void(X&). That would mean that Y(X&) is the type of a function that returns a function. That's totally bogus. There is no such thing. Apparently, the decltype-based result_of is smart enough to see this as bogus, but the TR1 result_of, which only does dumb type shunting with metaprogramming hacks, doesn't notice the problem.
g() should be callable with function pointers, copyable and moveable-only functors (signatue void( X&)).
Again - the original code works for gcc, intel, msvc and clang (Linux) and fails for clang on MacOS X.
And hopefully now that I've explained it a second time, you no longer find it remarkable. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 29/11/12 03:20, Eric Niebler wrote:
On 11/28/2012 1:25 PM, Oliver Kowalke wrote:
2012/11/28 Oliver Kowalke <oliver.kowalke@gmail.com>
You are asking result_of to compute the result of calling a unary function that takes an X& with zero arguments. That's nonsensical. If you intend to call it with an X&, then ask it what the result is when called with an X&:
boost::result_of< Fn(X&) >::type
This should correctly report void regardless of whether result_of uses decltype or the TR1 result_of protocol.
OK, I got it. It's strange that clang 3.2 (c++11), gcc, ontel and msvc compile the code without errors on Loinux and Windows.
I've already explained this. Decltype-based result_of is only turned on by default for compilers that have strong-enough decltype support. That is currently only very recent clang versions. That does NOT include gcc, intel or msvc.
I thought I could the problem can be solved like the following code, but it does not compile for gcc (c++0x):
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template< typename Fn > void g( BOOST_RV_REF( Fn) ) { typedef typename remove_reference< Fn >::type Y; BOOST_STATIC_ASSERT(( is_same< void, typename result_of< Y( X &) >::type >::value)); } #else ... #endif
If Fn is void(&)(X&), then remove_reference<Fn>::type is void(X&). That would mean that Y(X&) is the type of a function that returns a function. That's totally bogus. There is no such thing. Apparently, the decltype-based result_of is smart enough to see this as bogus, but the TR1 result_of, which only does dumb type shunting with metaprogramming hacks, doesn't notice the problem.
I thought it automatically decayed to function pointers. That doesn't seem to be the case. result_of<F(Args...)> is supposed to work for any possibly const-qualified (and apparently reference-qualified too) type that is callable with args of type Args. But actually, the syntax of result_of itself prevents this since it doesn't work for function types. I never realized that. You need to force a decay manually to use it properly. Sorry for the remove_reference, it was bad advice.
participants (6)
-
Eric Niebler
-
Jeffrey Lee Hellrung, Jr.
-
Mathias Gaunard
-
Michel Morin
-
Oliver Kowalke
-
Peter Dimov