Re: a specialization in boost::result_of
cim20@metropolis-data.co.uk wrote:
On a tangential point:
the line:
typedef double (*FUNC)(char);
defines a type called FUNC which is a synonym for the function pointer
type double (*)(char)
so what does FUNC() mean?
It is the (unnamed) type of a function that takes no arguments and
returns FUNC.
By experimenting with gcc I find that the
"result type" of FUNC() is
double (*()())(char)
Remember, result_of abuses function types. result_of<FUNC()>::type
should be the type returned by calling FUNC with no arguments. Since
FUNC takes exactly one argument, calling it with no arguments is an
error. But without compiler help it's nasty (not sure if it's even
possible) to figure that out. The compromise rule in TR1 is that if the
implementation can't get the right answer, it should simply report the
return type of FUNC. So result_of<FUNC()>::type should be double under
the compromise rule, or a diagnostic because the code is ill-formed if
you have compiler support (which will almost certainly be required in
C++0x).
I can parse the meaning of double (*)(char) as "a type that indicates
a pointer to a function that returns a double and takes a char as an
argument" so how does one read double (*()())(char) ?
It's too early in the morning to read stuff like that. <g>
More importantly, why does
result_of<double (*)(char)> not work while result_of<double
(*()())(char)> does ?
typedef double (*FUNC)(char);
FUNC is a pointer to a function that takes an argument of type char and
returns double.
print_type<std::tr1::result_of<FUNC()>::type>();
But keep in mind that FUNC doesn't take an empty argument list, so the
preceding is, in the abstract, ill-formed. The rule, for implementations
that can't get that right (because they don't have compiler hooks), is
that result_of gives you the return type of FUNC, i.e. double.
typedef double (*FUNC2())(char);
FUNC2 is (I'm pretty sure <g>) a function that takes no arguments and
returns a pointer to a function that takes one argument of type char and
returns double.
print_type<std::tr1::result_of<FUNC2>::type>();
print_type<std::tr1::result_of<FUNC>::type>(); // this line fails
result_of takes an argument that consists of a callable type followed by
a parenthesized argument list, disguised as a function type. So in the
expression result_of<FUNC2>, the actual meaning of FUNC2 which I gave
above doesn't matter. result_of uses its own rules to decide how to
handle that type. It may well be that it can be parsed as a callable
type and an argument list. It's too complicated for my feeble brain.
But let's build up from the bottom instead of trying to work from the
top down. To get the return type of FUNC when called with no arguments,
we'd say result_of<FUNC()>::type.Now, since typedefs for functions deal
with argument lists and return types, a full typedef for FUNC() would
name a function that takes no arguments and returns an object of type FUNC:
typedef FUNC F();
and you can now say result_of<F>::type, which is equivalent to
result_of<FUNC()>. Expanding FUNC in that typedef produces
typedef double (*F())(char);
Hey, that's the same as your FUNC2!
So it should now be clear <g> why result_of<FUNC2> works, and
result_of<FUNC> doesn't. And it should be equally clear why you really
don't want to write typedefs for these things.
--
-- Pete
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]