Subject: Re: [boost] (Boost.)Overload vs Boost.Functional/OverloadedFunction (was Re: Status of proposed boost.overload?)
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2012-03-27 18:35:57


AMDG

On 03/27/2012 02:10 PM, lcaminiti wrote:
>
> BTW, I wasn't able to handle polimorphic functions. For example, the
> following will not work :(
>
> struct poly {
> template<typename T>
> void operator()( T const& x ) { std::cout << "poly" << std::endl; }
> };
>
> void mono( int x, int y ) { std::cout << "mon" << std::endl;
>
> overload_function< void(int, int), /* some type which I couldn't figure out
> */ > f(mono, poly);
> f(1, 2); // call mono
> f(123); // call poly
> f("abc"); // call poly
>
> // or even harder
> auto g = make_overloaded_function(mono, poly);
> g(1, 2); // call mono
> g(123); // call poly
> g("abc"); // call poly
>
> Can your library handle polymorphic functions?
>

No. This is fundamentally impossible.
Let's ignore the overload part for now.

We're trying to define a class F, such that:

For any types T and U, such that T is
copy constructible and T is callable
with an argument of type U:

Given an object t of type T, and
an object u of type U.

F f(t);

shall be valid and f shall store a copy of t.
Call this copy t_f. Now, f(u) shall compile
and shall call t_f(u).

Let's assume that F exists.
Now, suppose that T is declared only in
translation unit A, and U is declared
only in translation unit B. Further, suppose
that T is a class type with a templated function
call operator. The constructor F(t) can be
executed in A, and the function call can be
executed in B. The result must call T::operator()<U>.
However, T and U are never available in the
same translation unit, so T::operator()<U> cannot
be instantiated. -><-

Therefore, we can conclude that type erasure
cannot handle polymorphic functions like this,
without adding further restrictions.

Some possibilities are:
a) type erase the argument to T::operator().
b) Limit T and/or U to some fixed set of types.
   (a la Boost.Variant)
c) Allow T/U pairs to be registered dynamically
   and fail at runtime if there is no viable
   function.

(As the author of a library for general type
erasure, I've spent an inordinate amount of
time thinking about this problem.)

In Christ,
Steven Watanabe