Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2001-09-19 07:12:26


From: "Darin Adler" <darin_at_[hidden]>
> on 9/18/01 5:11 PM, Douglas Gregor at gregod_at_[hidden] wrote:
>
> > But this requires partial ordering of function templates when a function
> > pointer is passed in, which breaks on a _lot_ of compilers.
>
> Your response inspired me to study the C++ standard section on partial
> ordering of function templates. My testing indicates that partial ordering
> of function templates works perfectly in the Metrowerks compiler even in
> cases where a function pointer is passed in. But your suggested fix for
the
> function constructor won't work. Here's why:
>
> template<typename F> function(const F& f);
> template<typename OR> function(OR (*f)());
>
> According to the rules in the standard (14.5.5.2), neither of these
function
> templates is at least as specialized as the other! So there's an
ambiguity.
> The rule is that you perform argument deduction on each of the templates,
> using parameters constructed by substituting unique types for each of the
> template parameters of the other. Trying to pass the function pointer type
> into the "const F&" results in a deduction that succeeds, but the deduced
> parameter type is not an exact match. The function pointer has to be
> implicitly converted into a const reference to a function pointer, which
is
> not allowed (14.5.5.2p4).

Your analysis is incorrect, I believe. A reference binding doesn't count as
an implicit conversion. Consider this simpler example:

template<class T> void f(T const &);
template<class T> void f(T * const &);

The problem with 14.5.5.2 is that it does not specify how the argument
deduction is performed. The two possibilities are (1) deduction as in a
function call, and (2) deduction as in taking a function address.

Under (1) the function pointer version is more specialized. Under (2)
neither is. See

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#214

The modification

template<class F> void f(F const &);
template<class R> void f(R (* const &)());

'works' under both; but then the problem is that some compilers bind a const
reference to a function (which is currently not allowed but there is a
defect report against it - #295) and will therefore prefer the first
version. ;-)

My own opinion is that

template<class F> void function(F f);

is not that bad. The standard library always takes function objects by
value.

--
Peter Dimov
Multi Media Ltd.

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk