$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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