#include <type_traits> 
#include <iostream>

//classes
struct A { virtual ~A(){} virtual void print(){std::cout << "A\n";}};
struct B : A { virtual void print(){std::cout << "B\n";}};
struct C : A { virtual void print(){std::cout << "C\n";}};
struct D : A { virtual void print(){std::cout << "D\n";}};

//polymorphic local forwarder
template<class Type, class FuncType>
auto poly_local(FuncType func) -> decltype(func(std::declval<Type&>()))
{
    Type local;
    return func(local);
}

//test function
char dowork(A& a) {
    a.print();
    return '8';
}
//test functionoid with parameters
struct dowork2 {
    int parameter;
    explicit dowork2(int p) :parameter(p) {}
    int operator()(A& a) const{
        a.print();
        std::cout << parameter << '\n';
        return parameter;
    }
};

//demo
int main() {
    int some_var = 2;
	
    switch (some_var) {
    case 1: poly_local<A>(dowork); break;
    case 2: poly_local<B>(dowork); break;
    default: poly_local<C>(dowork); break;
    }

    switch (some_var) {
    case 1: poly_local<B>(dowork2(3)); break;
    case 2: poly_local<C>(dowork2(2)); break;
    default: poly_local<A>(dowork2(1)); break;
    }
    return 0;
}