C ++ шаблон специализация на функциях - PullRequest
15 голосов
/ 08 июля 2011

Я играю со специализацией по шаблонам и обнаружил проблему, которую не могу решить; это мой код:

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 ]

17 голосов
/ 08 июля 2011

Частичная специализация шаблонов функций не допускается.Херб Саттер объясняет, почему в своей статье «Почему бы не специализировать шаблоны функций?» .

Чтобы обойти это ограничение, вам нужно вместо этого использовать шаблоны классов.Затем вы можете написать обычный шаблон функции, который использует этот шаблон класса.

Эта конкретная ошибка, которую вы получаете, заключается в том, что вы забыли второй параметр в своей специализации.Если вы вместо этого:

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>' isне допускается

7 голосов
/ 08 июля 2011

Функции не могут быть частично специализированными. Чтобы обойти это, попросите функцию шаблона вызвать функцию в классе:

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 голосов
/ 08 июля 2011

Частичная специализация шаблонов функций не допускается .

Чтобы обойти это, вы можете сделать test статическим членом шаблона класса и частично специализировать класс.

2 голосов
/ 08 июля 2011

Вы можете обойти это с помощью вспомогательного класса. Для наглядности:

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();
}
...