Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deduce first template parameter in multiple parameter template by parameter

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.

like image 930
Blackclaws Avatar asked Jan 27 '16 10:01

Blackclaws


People also ask

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

What is function template with multiple parameters in C++?

Multiple parameters can be used in both class and function template. Template functions can also be overloaded. We can also use nontype arguments such as built-in or derived data types as template arguments.

Can there be more than one arguments to templates?

Can there be more than one argument to templates? Yes, like normal parameters, we can pass more than one data type as arguments to templates.

What is template argument deduction in C++?

Class Template Argument Deduction (CTAD) is a C++17 Core Language feature that reduces code verbosity. C++17's Standard Library also supports CTAD, so after upgrading your toolset, you can take advantage of this new feature when using STL types like std::pair and std::vector.


1 Answers

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)
like image 115
eerorika Avatar answered Sep 30 '22 14:09

eerorika