Anycorn
Anycorn

Reputation: 51555

C++ ambiguous template instantiation

the following gives me ambiguous template instantiation with nvcc (combination of EDG front-end and g++). Is it really ambiguous, or is compiler wrong? I also post workaround à la boost::enable_if

template<typename T> struct disable_if_serial { typedef void type; };
template<> struct disable_if_serial<serial_tag> { };

template<int M, int N, typename T>
__device__
//static typename disable_if_serial<T>::type
void add_evaluate_polynomial1(double *R,
                         const double (&C)[M][N], double x,
                         const T &thread) {
    // ...
}

template<size_t M, size_t N>
__device__
static void add_evaluate_polynomial1(double *R,
                                     const double (&C)[M][N], double x,
                                     const serial_tag&) {
    for (size_t i = 0; i < M; ++i)
        add_evaluate_polynomial1(R, C, x, i);
}

// ambiguous template instantiation here.
add_evaluate_polynomial1(R, C, x, serial_tag());  

Upvotes: 3

Views: 2235

Answers (2)

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 507313

I have tested the code on Clang, GCC and Comeau. Comeau rejects it while GCC and Clang accept it. I think that for both groups of compilers there can be made points

  • Comeau follows the C++03 rule, which requires an "exact match (so the deduction does not rely on implicit conversions)" for the deduced template arguments. However this specification was horribly underspecified and has been completely rewritten for C++0x.

  • Clang and GCC seem to implement the rewritten rule, and this rule better specifies what "exact match" means. This specification goes fine with the different types of the array dimensions.

In any case, if you want to go fine with all compilers, then really go by the accepted answer and change the non-type parameter types to a common type :)

Upvotes: 3

jpalecek
jpalecek

Reputation: 47770

AFAIK, the problem is that you have the nontype arguments inconsistently typed (that is, M and N are int here, but size_t there). This means not all template variable assignments from one can be used in the other, which means there is no partial ordering, hence the error message.

Unite the template nontype argument types and it should work.

Upvotes: 7

Related Questions