Reputation: 458
I am trying to code the Horner alogrithm using a meta programming code. Unfortunately the code doesn't compile. Here you find the compiler error:
In instantiation of ‘const int tuple_nth_element_v<1u, int, 1>::value’:
----> LINE 1 <---- recursively required from ‘const int tuple_nth_element_v<2u, int, 2, 1>::value’
required from ‘const int tuple_nth_element_v<3u, int, 1, 2, 1>::value’
----> LINE 2 <---- recursively required from ‘constexpr const double Horner_Impl<5, 2ul, int, 1, 2, 1>::value’
required from ‘constexpr const double Horner_Impl<5, 3ul, int, 1, 2, 1>::value’
required from ‘constexpr const double Horner<5, int, 1, 2, 1>::value’
required from here
incomplete type ‘tuple_nth_element_v<0u, int>’ used in nested name specifier
The code used the following:
template<unsigned int N, class T, T... t>
struct tuple_nth_element_v;
template <class T, T t0, T... t>
struct tuple_nth_element_v<0, T, t0, t...> {
static const T value = t0;
};
template <unsigned int N, class T, T t0, T... t>
struct tuple_nth_element_v<N, T, t0, t...> {
---> LINE1 <----
static const T value = tuple_nth_element_v<N-1, T, t...>::value;
};
template<int x, std::size_t i, class T, T... a>
struct Horner_Impl
{
----> LINE 2 <----
constexpr static double value = Horner_Impl<x, i - 1, T, a...>::value * x +
tuple_nth_element_v<sizeof...(a) - i, T , a...>::value;
};
template<int x, class T, T... a>
struct Horner_Impl<x, 0, T, a...>
{
constexpr static double value = tuple_nth_element_v<sizeof...(a), T , a...>::value;
};
template<int x, class T, T... a>
struct Horner
{
constexpr static double value = Horner_Impl<x, sizeof...(a), T, a...>::value;
};
Someone would have an idea?
Upvotes: 1
Views: 2231
Reputation: 3107
This way seems a little bit more straightforward to me because it takes one coefficient off the pack on each recursion instead of using a helper class to perform an indexed enumeration:
#include <iostream>
template <int x, typename T, T a_n, T ...a>
struct Horner {
constexpr static double value = Horner<x, T, a...>::value * x + a_n;
};
template <int x, typename T, T a_n>
struct Horner<x, T, a_n> {
constexpr static double value = a_n;
};
int main() {
double y = Horner<3, int, 5, 3, 2, 8>::value;
std::cout << y << "\n";
}
Upvotes: 3
Reputation: 4637
In tuple_nth_element_v
, you recursively scroll through the parameter pack until N == 0
, when N
is the number of elements in the parameter pack. When N == 0
, you can't have any elements in the parameter pack. The specialization for N == 0
requires at least one element in the parameter pack, and so it can't be selected. The only one that matches is the un-specialized class, which has no definition.
With Horner<2, int, 1, 2>
, there is a series like this:
value = tuple_nth_element_v<2, int, 1, 2>::value = tuple_nth_element_v<1, int, 2>::value = tuple_nth_element_v<0, int>::value;
That last instantiation is the source of the error.
I'm not familiar with the algorithm, but I think your solution is to change
template <class T, T t0, T... t>
struct tuple_nth_element_v<0, T, t0, t...>
to
template <class T, T t0, T... t>
struct tuple_nth_element_v<1, T, t0, t...> //N is now 1, not 0
and in Horner_Impl
, change
constexpr static double value = ... tuple_nth_element_v<sizeof...(a) - i, T , a...>::value;
to
constexpr static double value = ... tuple_nth_element_v<sizeof...(a) - i + 1, T , a...>::value; //note the + 1
Upvotes: 0