C++函数模板特化

20

我正在尝试模板特化,但发现了一个无法解决的问题;以下是我的代码:

template<int length, typename T>
void test(T* array)
{
    ...
    test<length-1>(array);
}

template<typename T>
void test<0>(T* array)
{
    return;
}

我想要做的是在模板中传递待处理内容的长度。

问题是,这样编译会使输出无限延迟:

a.cpp:83:43: error: template-id 'test<0>' in declaration of primary template
a.cpp: In function 'void test(T*) [with int length= -0x000000081, T = int]':
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x000000080, T = int]'
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x00000007f, T = int]'
a.cpp:77:9:   [ skipping 151 instantiation contexts ]
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= 28, T = int]'
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= 29, T = int]'
...
a.cpp: In function 'void test(T*) [with int length= -0x000000082, T = int]':
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x000000081, T = int]'
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x000000080, T = int]'

最后两行与前面的行几乎相同。

在我看来,它似乎没有捕捉到专业化,因此:

a.cpp:83:43: error: template-id 'test<0>' in declaration of primary template

我猜想您的问题是关于函数模板的部分特化问题,是吗?如果是这样,解决方案是使用结构体并对其进行特化。

那么,我的猜测正确吗?

4个回答

23

函数模板的局部特化是不允许的。Herb Sutter在他的文章《为什么不特化函数模板?》中解释了原因。

要解决这个限制,你需要使用类模板。然后,你可以编写一个使用该类模板的常规函数模板。

你收到的具体错误是因为你忘记了特化中的第二个参数。如果你像这样操作:

template<int length, typename T>
void test(T* array)
{
    //...
    test<length-1,T>(array);
}


template<typename T>
void test<0,T>(T* array)
{
    return;
}

GCC抱怨如下:

错误:不允许函数模板偏特化“test<0, T>”


该错误信息表示函数模板的偏特化“test<0,T>”是不被允许的。

那么我的解决方案是什么呢?使用结构体并创建一个包装函数? - Skeen
2
为什么不允许呢?只是好奇。 - Skeen
1
@Skeen引用文章中的话,“你不能对它们进行部分特化--这基本上是因为语言规定你不能这样做”。有一个脚注说,这被考虑作为C++未来版本的一项语言功能(在当时可能是C++11)。 - Chuu
谢谢您的回答。我有一个来自提供的链接的问题。在示例2中,编译器如何决定(c)是(a)还是(b)的特化? - CodePro_NotYet

9

函数无法部分特化。为了解决这个问题,可以让您的模板函数调用类中的一个函数:

template<int length, typename T>
struct helper
{
    static void go(T* array)
    {
        ...
        helper<length-1, T>::go(array);
    }
};

template<typename T>
struct helper<0, T>
{
    static void go(T* array)
    {
        ...
    }
};

template<int length, typename T>
void test(T* array)
{
    ...
    helper<length, T>::go(array);
}

3

函数模板的部分特化是不被允许的

为了解决这个问题,您可以将test作为类模板的静态成员,并对该类进行部分特化。


2
您可以使用辅助类进行解决。以下是一个示例:

您可以用一个辅助类来解决此问题。例如:

template<typename T, typename U> struct helper_t {
    static int foo () { return 0; }
};

template<typename T> struct helper_t<T,T> {
    static int foo () { return 1; }
};

template <typename T, typename U>
int frob () {
    return helper_t<T,U>::foo();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接