
On 5/21/07, Eric Niebler <eric@boost-consulting.com> wrote:
Peter Dimov wrote:
Eric Niebler wrote:
I've noticed something odd about the specification of tr1::result_of. In result_of<F()>::type, if F is a class type that doesn't have a nested result_type typedef, the result is "void". This is only true for F(); that is, when there are no arguments.
This special case is needed in situations such as:
template<class F> struct X { F f_;
result_of<F()>::type operator()() { return f_; }
template<class A1> result_of<F(A1)>::type operator()(A1& a1) { return f_(a1); }
// ... };
where X can be instantiated with non-nullary function objects, or with types that aren't function objects at all, as in:
X<int> x;
The above instantiates the declaration of X::operator()(), which attempts to instantiate result_of<int()>, which would fail without the kludge.
Well, my reading of the spec makes the program ill-formed. F needs to be a class type for this odd rule to kick in.
But ... yech. And the different behavior between foo and bar in my example is that we know how to test for member typedefs but not for member templates.
I agree with your reading. I think the above is ill-formed according to section 3.4/3. Incidentally, we do know how to test for member templates now. Here's a thread archive discussing my patch to MPL that does this: http://tinyurl.com/2os8fl. So, it would be possible to implement a result_of that deduces the correct return type in corner cases like your example without decltype. But decltype is a much better all around solution. Daniel