简体   繁体   中英

Ambiguous call on overloaded variadic template function

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!

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.

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM