C ++: шаблон кандидата игнорируется: недопустимый явно заданный аргумент для параметра шаблона - PullRequest
5 голосов
/ 25 декабря 2011

У меня есть заголовок этой функции:

template <
    bool src_alpha,
    int sbpp, int dbpp,
    typename T1, typename T2,
    Color (*getFunc)(T1 data, Uint8* addr),
    void (*putFunc)(T2 data, Uint8* addr, Color c)
>
static void OperateOnSurfaces(T1 data1, T2 data2, SDL_Surface * bmpDest, SDL_Surface * bmpSrc, SDL_Rect& rDest, SDL_Rect& rSrc)

Вот как я его использую:

OperateOnSurfaces<
    true,
    32, 32,
    SDL_PixelFormat*, SDL_PixelFormat*,
    GetPixel<true,32>, PutPixel<true,true,32> >(
    bmpSrc->format, bmpDest->format,
    bmpDest, bmpSrc, rDest, rSrc);

Это GetPixel и PutPixel:

template<bool alpha, int bpp>
static Color GetPixel(SDL_PixelFormat* format, Uint8* addr) { /* .. */ }

template<bool alpha, bool alphablend, int bpp>
static void PutPixel(SDL_PixelFormat* format, Uint8* addr, Color col) { /* .. */ }

И я получаю эту ошибку:

note: candidate template ignored: invalid explicitly-specified argument for template parameter 'getFunc' [3]

Почему?

1 Ответ

6 голосов
/ 25 декабря 2011

Я подозреваю, что все эти функции являются свободными функциями. Когда вы объявляете свободную функцию static, она получает внутреннюю связь. Параметры не типового шаблона, в C ++ 03 должны иметь внешнюю связь . Просто удалите static перед функциями.

template <
    bool src_alpha,
    int sbpp, int dbpp,
    typename T1, typename T2,
    char (*getFunc)(T1 data, unsigned* addr),
    void (*putFunc)(T2 data, unsigned* addr, char c)
>
void OperateOnSurfaces(){}

template<bool alpha, int bpp>
char GetPixel(void* format, unsigned* addr);

template<bool alpha, bool alphablend, int bpp>
void PutPixel(void* format, unsigned* addr, char col);

int main(){
    OperateOnSurfaces<
        true,
        32, 32,
        void*, void*,
        GetPixel<true,32>, PutPixel<true,true,32> >();
}

Этот модифицированный пример прекрасно компилируется на Clang 3.1 и GCc 4.4.5 в режимах C ++ 98 и C ++ 11, без предупреждений. Если я оставлю static в, я получу сообщение об ошибке + примечание к тому, что вы получили с Clang, и GCC выплевывает жизненно важную информацию (прокрутите вправо, "не имеет внешней связи"):

15:02:38 $ g++ t.cpp
t.cpp: In function ‘int main()’:
t.cpp:21: error: ‘GetPixel<true, 32>’ is not a valid template argument for type ‘char (*)(void*, unsigned int*)’ because function ‘char GetPixel(void*, unsigned int*) [with bool alpha = true, int bpp = 32]’ has not external linkage
t.cpp:21: error: ‘PutPixel<true, true, 32>’ is not a valid template argument for type ‘void (*)(void*, unsigned int*, char)’ because function ‘void PutPixel(void*, unsigned int*, char) [with bool alpha = true, bool alphablend = true, int bpp = 32]’ has not external linkage
t.cpp:21: error: no matching function for call to ‘OperateOnSurfaces()’

(C++03) §14.3.2 [temp.arg.nontype] p1

A шаблон-аргумент для нетипового, не шаблонного шаблон-параметра должен быть одним из:

  • [...]

  • адрес объекта или функции с внешней связью [...]

  • [...]

Обратите внимание, что C ++ 11 изменил формулировку и теперь также поддерживает функции с внутренней связью:

(C++11) §14.3.2 [temp.arg.nontype] p1

A шаблон-аргумент для нетипового, не шаблонного шаблон-параметра должен быть одним из:

  • [...]

  • константное выражение (5.19), которое обозначает адрес объекта со статической продолжительностью хранения и внешней или внутренней связью или функцию с внешней или внутренней связью [. ..]

  • [...]

Clang в настоящее время не подчиняется этому в режиме C ++ 11, он по-прежнему допускает только функции с внешней связью.

...