
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