6

I'm trying to write function that counts scalar product for two vectors. Here is the code and it works.

    template <int N> 
    int scalar_product (std::vector<int>::iterator a, 
                        std::vector<int>::iterator b) {
        return (*a) * (*b) + scalar_product<N - 1>(a + 1, b + 1);
    }

    template <>
    int scalar_product<0>(std::vector<int>::iterator a,
                          std::vector<int>::iterator b) {
        return 0;
    }

But here is the problem - i want to replace this iterators with template type, so that signature of function will look smth like this

    template <typename Iterator ,int N> 
    int scalar_product (Iterator a, Iterator b) {
        return (*a) * (*b) + scalar_product<N - 1>(a + 1, b + 1);
    }

    template <typename Iterator>
    int scalar_product<0>(Iterator a,
                          Iterator b) {
        return 0;
    }

But this doesn't work - I get compile error C2768: illegal use of explicit template arguments. It seems silly, but I couldn't find out what should I change to avoid this error.

htzfun
  • 1,231
  • 10
  • 41
  • See this: http://stackoverflow.com/questions/3716799/partial-specialization-of-function-templates – Nim Dec 09 '13 at 08:51
  • Why not use [`std::inner_product`](http://en.cppreference.com/w/cpp/algorithm/inner_product)? Is inlining the loop so important to you? – gwiazdorrr Dec 09 '13 at 08:58
  • @gwiazdorr Actually, it's just part of codereview task, so that it expects using of templates as inlining loop. – htzfun Dec 09 '13 at 09:03
  • 1
    Well, you still can use free functions for that. Check out my answer. – gwiazdorrr Dec 09 '13 at 09:15

2 Answers2

5

Actually, you don't have to use types - I find them pretty cumbersome and their semantics are different. You can not partially specialise a function, but you can overload them and make them behave like specialisations by providing default parameters values:

#include <type_traits>

template <typename Iterator>
int scalar_product(Iterator a, Iterator b, std::integral_constant<int, 0> = std::integral_constant<int, 0>()  ) 
{
    return 0;
}

template <int N, typename Iterator> 
int scalar_product (Iterator a, Iterator b, std::integral_constant<int, N> = std::integral_constant<int, N>() ) 
{
    return (*a) * (*b) + scalar_product(a + 1, b + 1, std::integral_constant<int, N-1>() );
}

int foo()
{
    int a[] = { 1, 2, 3, 4 };
    int b[] = { 1, 1, 1, 1 };
    return scalar_product<4>(a, b); // returns 10
}
gwiazdorrr
  • 6,181
  • 2
  • 27
  • 36
4

(AFAIK) there is no support for partial specialization of function templates, to obtain this functionality, you need to do it slightly differently, something like:

template <int N>
struct scalar
{
  template <typename Iterator>
  static int product(Iterator a, Iterator b)
  { (*a) * (*b) + scalar<N - 1>::product(a + 1, b + 1); }
};

template <>
struct scalar<0>
{
  template <typename Iterator>
  static int product(Iterator a, Iterator b)
  { return 0; }
};
Nim
  • 33,299
  • 2
  • 62
  • 101