I see this as a good and correct question, however there is no general solution besides using the template parameter at the class level. What you tried to achieve in your question - using a typedef inside a function and then accessing it in the whole class is impossible.
Erase Styles
Only if you impose certain restrictions on your constructor options are there several alternatives. In this regard, here is an example of type erasure in which the operator() some given object is stored inside the variable std::function<void()> .
struct A { template<typename T> A(T const& t) : f (std::bind(&T::operator(), t)) {} void operator()() const { f(); } std::function<void()> f; }; struct B { void operator()() const { std::cout<<"hello"<<std::endl; } }; int main() { A(B{}).operator()();
Demo
Note, however, the assumptions underlying this approach: it is assumed that all past objects have an operator of this signature (here void operator() ), which is stored inside a std::function<void()> (relative to the storage of the function- member, see here ).
Inheritance
In a sense, erasing a type thus looks like "inheritance without a base class" - instead, you can use a common base class for all constructor parameter classes with a virtual bracket operator, and then pass the base class pointer to your constructor.
struct A_parameter_base { void operator()() const = 0; }; struct B : public A_parameter_base { void operator()() const { std::cout<<"hello"<<std::endl; } }; struct A { A(std::shared_ptr<A_parameter_base> _p) : p(_p) {} void operator()() { p->operator(); } std::shared_ptr<A_parameter_base> p; }
This is similar to the code in your question, only that it does not use void -pointer, but a pointer to a specific base class.
Both approaches, type erasure, and inheritance are similar in their applications, but type erasure may be more convenient as you get rid of the common base class. However, the inheritance approach has the added benefit that you can restore the original object using multiple submit
It also shows the limitations of both approaches. If your statement is not void , but instead returns an unknown different type, you cannot use the above approach, but you must use templates. Parallel inheritance: you cannot have a virtual function template.