Re: deducing return value on a template function pointer
Am 18.11.2010 03:03, schrieb Andy Champ:
I have a declaration that, simplified, says this
template <typename A, typename A(*B)(void) > class Z
{
public:
bool operator()() const
{
return B() < B();
}
};
I assume there is a typo and read the begin of the definition of the template
definition as:
template <typename A, A(*B)(void) > class Z
{
...
};
Class Z has a template parameter B which is a pointer to a function
taking no params and returning A. The operator() method calls the
function twice, and compares the result.
I can instantiate this, and call into it
Z<int, getchar> y;
Let me just warn you, that this is not portable. getchar may have C language
linkage and this is not required to be compatible to the C++ language linkage of
the function pointer within Z.
bool x = y();
passing in getchar - a function that returns an int. I have no interest
whatsoever in the return type of getchar - I just want to know how the
results compare. Is there a way of getting the syntax so that it will
_deduce_ the return parameter type?
I'm not aware of a feasible way in C++03, but there are alternatives in C++0x
that satisfy the auto-deduction criterion. I start with the obvious one, which
would be a lambda-expression (with the additional advantage that it would be
neutral against language linkage issues):
auto closure = []() { return getchar() < getchar(); };
typedef decltype(closure) closure_t;
You can use closure_t as the predicate type of a set, for example.
[But of-course above predicate function does not satisfy the criteria for a
strictly weak ordering at all]
Additionally, constexpr functions will allow to support some interesting idioms.
The following should be well-formed, even though it looks somewhat complicated.
Assume the following helper definitions:
template<class>
struct ret_type;
template<class R>
struct ret_type<R()> { typedef R type; };
template<class F>
struct addr_holder {
F* p;
typedef typename ret_type<F>::type type;
constexpr addr_holder(F* p) : p(p) {}
};
template<class F>
constexpr addr_holder<F> make_holder(F* p) { return addr_holder<F>(p); }
Now we can deduce a value of a concrete specialization of Z as follows:
constexpr auto h = make_holder(getchar);
Z<decltype(h)::type, h.p> z;
This takes advantage from the fact that 'h.p' is an address-constant expression
that can thus be used as an argument for a non-type template parameter of
pointer type [I expect that this was not the kind of auto-deduction that you
would have preferred, though ;-)].
For those who really want to know - I actually want to pass Z in as the
predicate to std::set, and B is a pointer to a member function. But
this is simplified...
It looks to me that you should use lambda-expressions, if you can. I assume that
you have a separate source for the actual object that is provided as first
argument of the pointer-to-member dereference operator, because otherwise they
introduce an additional layer of complexity that is not possible to auto-deduce.
What I mean is: You cannot deduce in C++ the object and the pointer-to-member
address from a single expression, e.g. like this (warning: no real C++):
struct C {
void foo();
} c;
auto pm = &c.foo;
where pm is also some kind of lambda closure that contains both an object and
the referred to pointer (You can come near to that via std::bind, but not that
near). Delphi can this and I would like to see this kind of deduction in C++ as
well - not for C++0x, though.
HTH & Greetings from Bremen,
Daniel Kr??gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]