Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiation of function template with variadic parameter pack

Tags:

c++

c++11

c++14

Suppose say I have this code:

template<int... Us>
struct Matrix{};

template<int... U1, int... U2>
auto compute(Matrix<U1...>, Matrix<U2...>){return 0;}

Matrix<1> a; Matrix<2,3> b;
Matrix<1,2> c; Matrix<3> d;

int main(){   
    compute(a,b);
    compute(c,d);
    auto fp = &compute<1,2,3>;
    fp(a,b);
    fp(c,d);
}

Would the two compute() calls instantiate just one function template i.e. compute<1,2,3> or would there be two different instantiations depending on the arguments?

I wanted to confirm this by taking a function pointer to the particular instantiation and see if I could call the function with the 2 different sets of arguments using the same function pointer but I get the following errors at the line where I call fp(a,b):

[x86-64 gcc 8.2 #1] error: could not convert 'a' from
'Matrix<#'nontype_argument_pack' not supported by
dump_expr#<expression error>>' to 'Matrix<#'nontype_argument_pack' not
supported by dump_expr#<expression error>>'
like image 728
MSS Avatar asked Jan 01 '23 12:01

MSS


1 Answers

Parameter packs are greedy.

&compute<1,2,3> is, in pseudo-code, &compute< U1={1,2,3}, U2={} >.

Getting a pointer to the individual computes is annoying.

template<class U1s, class U2s>
struct get_computer;
template<int...U1, int...U2>
struct get_computer<std::integer_sequence<int, U1...>, std::integer_sequence<int, U2...>> {
  using compute_type = int(*)(Matrix<U1...>, Matrix<U2...>);
  compute_type operator()() const { return compute; }
};

we can then do

auto fp1 = get_computer<std::integer_sequence<int, 1>, std::integer_sequence<int, 2, 3>>{}();
auto fp2 = get_computer<std::integer_sequence<int, 1, 2>, std::integer_sequence<int, 3>>{}();

and fp1 and fp2 are different types.

like image 91
Yakk - Adam Nevraumont Avatar answered Jan 25 '23 23:01

Yakk - Adam Nevraumont