1
votes

I have a numeric method coded using Variadic templates. I want to pass a mixture of parameters to it, some of type double and some of type vector. Minimal example;

template<typename... Ts>
using custom_function_t = double(*) (double, Ts...);

template<typename... Ts> 
double BiPart(double min, double max,custom_function_t<Ts...> f,Ts... args)
double FunctionA(double A, double a, double b, vector<double> &C);
int main()
{
    double a=0, b=1,x=0, y=1;
    vector<double> C;
    BiPart(x,y,FunctionA, a,b, &C);
    return(0);
}

double FunctionA(double A, double a, double b, vector<double> &C)
{
some stuff here
}

I get the errors: 'no matching function for call to 'Bipart(...)'' 'Template argument deducation/substitution failed: inconsistent parameter pack deducation with 'std::vector&' and 'std::vector''.

2
Are you quite sure that you're compiling this program? It has several typos and results in different compilation error than what you're asking about. - eerorika

2 Answers

0
votes

Weird, the full error I get from gcc (when I remove the ampersand from in front of C) is:

balls.cpp: In function ‘int main()’:
balls.cpp:15:34: error: no matching function for call to ‘BiPart(double&, double&, double (&)(double, double, double, std::vector<double>&), double&, double&, std::vector<double>&)’
     BiPart(x,y,FunctionA, a,b, C);
                              ^
balls.cpp:15:34: note: candidate is:
balls.cpp:9:8: note: template<class ... Ts> double BiPart(double, double, custom_function_t<Ts ...>, Ts ...)
 double BiPart(double min, double max,custom_function_t<Ts...> f,Ts... args);
        ^
balls.cpp:9:8: note:   template argument deduction/substitution failed:
balls.cpp:15:34: note:   inconsistent parameter pack deduction with ‘std::vector<double>&’ and ‘std::vector<double>’
     BiPart(x,y,FunctionA, a,b, C);
                              ^

So it clearly says it's trying to match a vector<double>& with another vector<double>& but later in the error message forgets that it's dealing with a reference. Compiler bug maybe? Or just c++ being c++.

I know this doesn't answer your question but if you only want to borrow the vector from BiPart you can pass it as a vector<double>* (instead of a reference) and it will work. And if you want to move the data into the BiPart call without copying it you can make the function argument a vector<double>&& and then call BiPart with move(C). That compiles too.

0
votes

You're probably actually calling that function like this:

BiPart(x,y,FunctionA, a,b, C);

and not with a pointer to the vector as in your post, right?

If so, the error message is actually pretty descriptive. What happens is something like this: the last parameter you're passing in, C, is used in type deduction two times, once for the argument f and once for the argument args. In the first case, because of how FunctionA is declared, it's type is deduced as std::vector<double>&. In the second case it gets deduced as a simple std::vector<double>, no reference. Because in both places you have used the same template argument, Ts..., these have to match exactly.

To fix this you can tackle the problem from different angles:

You can modify FunctionA to take the last argument by value instead of by reference. This will fix it because this time both deduced types will match (both will be deduced as std::vector<double>).

You can also unlink the two deduced types so they don't have to match, by using different argument typenames for the two functions:

template<typename... Ts, typename... OtherTs> 
double BiPart(double min, double max, custom_function_t<Ts...> f, OtherTs&&... args);

Notice the two template arguments. In this case the types deduced for argument f (still std::vector<double>& for the last) don't have to match exactly the types deduced for the rest of the arguments for BiPart (std::vector<double> for the last).