
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.