C ++ nested template with variable

I was wondering if it is possible to have a nested C ++ template and still be able to access the template values? To explain, here's what I currently have:

template <int first, int... tail>
struct ConstIntVector:ConstIntVector<tail...>
{};

template <int first>
struct ConstIntVector<first>
{}; 

template<int f1, int... t1>
int prod(const ConstIntVector<f1, t1...>, const int* a) {
    return f1 * (*a) + prod(ConstIntVector<t1...>(), a+1);
}

      

This way I can access the value f1

in my function prod

. But I would like to do it like this:

template<ConstIntVector<int f1, int... t1>>
int prod(const int* a) {
    return f1 * (*a) + prod<ConstIntVector<t1...>>(a+1);
}

      

Maybe?

+3


source to share


4 answers


Partial custom templates are not allowed for member functions. But you can use a helper structure:



namespace detail
{
    template <typename T>
    struct prodHelper;

    template <int f1, int... t1>
    struct prodHelper<ConstIntVector<f1, t1...> >
    {
        static int eval(const int* a) { 
            return f1 * (*a) + prodHelper<ConstIntVector<t1...>>::eval(a+1);
        }
    };
}

template <typename T>
int prod(const int* a) {
    return detail::prodHelper<T>::eval(a);
}

      

+4


source


Another option would be to use structures ConstIntVector

to carry useful information:



template <int First, int... Tail>
struct ConstIntVector {
   constexpr static int value = First;
   using tail = ConstIntVector<Tail...>;
};

template <int First>
struct ConstIntVector<First> {
   constexpr static int value = First;
   using got_no_tail = void;
}; 

template <class CIV, typename CIV::tail* = nullptr>
int prod(const int* a) {
    return CIV::value * (*a) + prod<typename CIV::tail>(a+1);
}

template <class CIV, typename CIV::got_no_tail* = nullptr>
int prod(const int* a) {
    return CIV::value * (*a);
}

      

+1


source


Just keep in mind that recursion is neither necessary nor desirable to solve these TMP problems. First, it's better to just define your vector like this:

template <int... Is>
struct ConstIntVector{};

      

This way you can also have vectors of length zero, which is handy when handling edge cases (we witness that it std::array

can be of length 0).

Next, let's write our product function. We'll change it in two ways: first we'll output an integer by trivially passing our value ConstIntVector

by value, and secondly we'll use package extensions to avoid recursion.

template<int... Is>
int prod(const int* a, ConstIntVector<Is...>) {
    int index = 0;
    int sum = 0;
    int [] temp = {(sum += (a[index++] * Is))...};
    return sum;
}

      

Using:

std::vector<int> v{1,2,3};
using v2 = ConstIntVector<4,5,6>;
std::cerr << prod(v.data(), v2{});

      

Live example: http://coliru.stacked-crooked.com/a/968e2f9594c6b292

Link for a highly optimized build example: https://godbolt.org/g/oR6rKe .

+1


source


What about

template<int I>
int prod(const int* a) {
    return I * (*a);
}

template<int I, int I2, int... Is>
int prod(const int* a) {
    return I * (*a) + prod<I2, Is...>(a + 1);
}

      

0


source







All Articles