Reputation: 51555
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
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
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