Deduce first template parameter in multiple parame

2019-08-14 07:52发布

问题:

First my question and then an explanation of what I'm trying to do as I might be approaching the problem wrong.

Is it possible to deduce the first template parameter in a multi parameter template from parameters while specifying the other parameters.

Example:

 template<class A, class B>
 B function(A object)
 { 
     return B(A);
 }

called like:

 function<BType>(AInstance);

I could not find a way to make this work.

EDIT: Another example might fit better to my problem below as indicated to me by the first comment I got

Example:

 template<class A, A::B foo>
 void function(A object)
 { 
     object.doSomethingWithTypeA::B(foo);
 }

called like:

 function<A::BInstance>(AInstance);

The difference is that the second template parameter is dependent on the specific type of the first so I can not switch the template parameters around.

Now for a description of what I am trying to do:

I am currently trying to create a templates universal functor class that can take either a free function or a member function and wrap it into a functor.

I succeeded in what I set out to do but now I want to make everything just a bit more user friendly. Currently the templated function to create a functor looks like:

template <class T, ReturnType (T::*Method)(FunctionArguments...)>
static constexpr UniversalFunctor Create(T* object) {
   return {object, MethodWrapper<T, Method>};
}

Right now to create a functor for a member function a user has to call

UniversalFunctor<ReturnType>::Create<ClassName, ClassFunction>(Object)

which is rather cumbersome.

Since Object has to be of type ClassName or at least be deducible to this I would have expected that a call like:

UniversalFunctor<ReturnType>::Create<ClassFunction>(Object)

should also be able to succeed as the ClassName parameter is deducible from the pointer passed. However that does not appear to be possible as ClassFunction is always treated as the first template parameter.

回答1:

No, you can only specify template arguments in order of declaration. So, you can specify the first and let second be deduced, but not the other way around.

You could write a wrapper for template:

template<class B, class A>
B function_wrapped(A&& object)
{ 
    return function<A, B>(std::forward<A>(object));
}

Now you can call:

function_wrapped<BType>(AInstance);

Of course, it would be simpler to just change the order of the parameters in the original function.

The second example is quite a bit more problematic.

If you can reverse the dependency of the types. By requiring that B defines an alias to A, then you could define:

template<class B, B foo>
void function(typename B::A object)

And call

function<decltype(BInstance), BInstance>(AInstance);

It's not very pretty.

The simplest solution would be to use runtime non-type arguments so that all types can be deduced.

template<class A, class B>
void function(A object, B foo)