模板函数专业化C++

Ann*_*ova 5 c++ templates metaprogramming

我需要实现算法,使用模板递归计算两个向量的标量积.

有我的代码:

#include <iostream>
#include <vector>

template<typename T, int Size>
T scalar_product(const std::vector<T> &a, const std::vector<T> &b)
{
    return a[Size - 1]*b[Size - 1] + (scalar_product<T, Size - 1>(a, b));
}

template<typename T>
T scalar_product<T, 0>(const std::vector<T> &a, const std::vector<T> &b) // error!
{
    return a[0] * b[0];
}

int main()
{
    std::vector<int> a(3, 1);
    std::vector<int> b(3, 3);

    std::cout << scalar_product<int, 3>(a, b);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我使用这种专业化T scalar_product<T, 0>(...),我会收到错误" 'scalar_product':非法使用显式模板参数 ".但是,如果我像这个T scalar_product(...)编译器报告一样删除它,递归将是无限的(因为没有专业化,据我所知).

这里有很多这类问题,但我找不到有用的答案.如何在不使用类的情况下专门化这个功能?先谢谢你了!

Pet*_*ter 4

没有部分函数模板专门化。您可以使用函子,它可以部分专业化:

template<typename T, int Size>
struct myFunctor
{
    T scalar_product(const std::vector<T> &a, const std::vector<T> &b)
    {
        static_assert(Size > 0,"Size must be positive!")
        return a[Size - 1]*b[Size - 1] + (myFunctor<typename T, Size - 1>::scalar_product(a, b));
    }
};
template<typename T>
struct myFunctor<T,1>
{
    T scalar_product(const std::vector<T> &a, const std::vector<T> &b)
    {
        return a[0] * b[0];
    }
};
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用std::enable_if来实现部分函数专业化之类的功能。

template<typename T, int Size>
typename std::enable_if<(Size>1), T>::type scalar_product(const std::vector<T> &a, const std::vector<T> &b)
{
    return a[Size - 1]*b[Size - 1] + (scalar_product<T, Size - 1>(a, b));
}
template<typename T, int Size>
T scalar_product(const std::vector<T> &a, const std::vector<T> &b, typename std::enable_if<(Size == 1), void*>::type x = nullptr)
{
    return a[0] * b[0];
}
Run Code Online (Sandbox Code Playgroud)

请注意,我在这两个函数中使用了 2 种不同的方式使用 std::enable_if 只是为了表明这两种方法都是可能的。这两个函数都可以像第一个函数一样在返回类型上使用enable_if,并且都可以像第二个函数一样在参数上使用它们。如需更多阅读,请参阅SFINAE

或者作为第三个选项,您可以像这样处理函数内部的专业化:

template<typename T, int Size>
T scalar_product(const std::vector<T> &a, const std::vector<T> &b)
{
    static_assert(Size > 0,"Size must be positive!")
    if (Size==1)
        return a[0] * b[0];
    return a[Size - 1]*b[Size - 1] + (scalar_product<T, (Size==1) ? Size : Size - 1>(a, b));
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果没有(Size==0) ? Size : Size - 1,编译器将为所有 int 值创建一个函数,否则就会失败。

  • @Peter“使用 char 而不是 int”是一个可怕的解决方法。使用 `scalar_product&lt;T, (Size==1) 更好地“保护”递归实例化?Size : Size - 1&gt;`: http://ideone.com/n5ZvKD (_edit:_ 或者使用你的 `Max&lt;Size - 1,0&gt;::value` 替代方案) (3认同)
  • 我认为它应该是“Size==1”而不是“Size==0”,并通过“static_assert”防止“Size&lt;=0”。 (2认同)