
On Wed, 28 Mar 2012 00:35:57 +0200, Steven Watanabe <watanabesj@gmail.com> wrote:
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. -><-
Clean exposition :)
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.
(b) is exactly what (Boost.)Overload does. It supports only a finite overload set and provides a method for setting up a copy of a polymorphic function object for each object target related to a call signature supported by both the given instantiation of the template class overload and the passed function object itself. Passing to another issue, do you know a way for getting the call signature of the call object type resulting from a lambda or phoenix bind expression at least in the case that the call object is monomorphic ? -- Marco -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/