Reputation: 1
I downloaded a C++ library to support multiple dimension array from github, when I built it using GCC8.2.0, the complier ran into a message saying an overrload function is ambiguous. Consider following code:
// basic function, set the length i for the dimension D
template<int Rank,int D>
void set_array(std::array<int,Rank>& A,int i)
{
A[D] = i;
}
// function with parameter pack, set the length for all dimensions recursively
template<int Rank,int D,typename... indices>
void set_array(std::array<int,Rank>& A,int i,indices... idx)
{
A[D] = i;
set_array<Rank,D+1>(A,idx...);
}
// class calls set_array in allocation
template<typename T,int Rank>
class MultiArray
{
private:
std::array<int,Rank> _dim = {{0}};
template<typename... indices>
void allocate(indices... idx) {
static_assert(sizeof...(idx) == Rank,
"NUMBER OF INDICES PASSED TO ALLOCATE DOES NOT MATCH RANK OF ARRAY");
set_array<Rank,0>(_dim,idx...);
}
};
// code to create object of above MultiArray class.
MultiArray<int, 1> a;
a.allocate(10)
The compiler error message is: call of overrloaded "set_array<1,0>(std::array&, int&) is ambiguous,
My understanding is when calling set_array<1, 0>(_dim, 10), the compiler can not know which one should be used because the parameter pack can be empty. I tried some ways to fix but failed. Is there any solution to help me out? Thank you in advance!
Upvotes: 0
Views: 109
Reputation: 180510
Your problem here is parameter packs are allowed to be empty. If you do have an empty pack, then
void set_array(std::array<int,Rank>& A,int i,indices... idx)
is just
void set_array(std::array<int,Rank>& A,int i)
which matches your non-variadic template. You need to handle having an empty parameter pack and easiest way to do that is to add an extra parameter like
template<int Rank,int D, typename First, typename... Rest>
void set_array(std::array<int,Rank>& A,int i,First first, Rest... rest)
{
A[D] = i;
set_array<Rank,D+1>(A,first, rest...);
}
and now if you call the function with only 2 parameters you'll get the non variadic overload and 3 or more will call the variadic one.
Upvotes: 1
Reputation: 31579
A straightforward way to solve this is to require at least one parameter for the second overload, by unrolling it once
template<int Rank,int D,typename index0, typename... indices>
Upvotes: 0