Ошибка использования функции в качестве нетипичного параметра шаблона - PullRequest
0 голосов
/ 03 февраля 2010

У меня есть этот шаблон:

        template <class SourceFormat, class DestFormat, void (*convert)(DestFormat, SourceFormat)>
    static void _draw(...);

И эти функции:

    template <class Class1, class Class2>
    inline static void convertNone(Class1& dest, Class2& source) {
        dest = source;
    };
    inline static void convertARGB_GREY(unsigned __int32& dest, unsigned __int8& source) {
        dest = source + (source << 8);
        dest += (dest << 16);
    };

Я использую шаблон в другой функции:

    void Blitter::draw(...) {

    if (...) {
        _draw<unsigned __int32, unsigned __int32, &convertNone>(...);
    } else {
        _draw<unsigned __int32, unsigned __int8, &convertARGB_GREY>(...); // ERRORS go here!
    }
}

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

Error   1   error C2440: 'specialization' : cannot convert from 'void (__cdecl *)(unsigned int &,unsigned char &)' to 'void (__cdecl *const )(unsigned char,unsigned int)'  d:\projects\fanlib\source\blitter.cpp   102
Error   2   error C2973: 'FANLib::Blitter::_draw' : invalid template argument 'void (__cdecl *)(unsigned int &,unsigned char &)'    d:\projects\fanlib\source\blitter.cpp   102

Полагаю, довольно очевидно, что я не полностью понимаю функции как параметры ...: - (

Заранее большое спасибо

Ответы [ 2 ]

5 голосов
/ 03 февраля 2010

В вашем коде есть несколько проблем.

В вашем коде при вызове _draw параметры SourceFormat и DestFormat шаблона _draw предоставляются с явными аргументами. Эти аргументы являются простыми не ссылочными целочисленными типами. Это автоматически означает, что третий параметр шаблона _draw должен быть функцией, которая также принимает свои аргументы по значению. То есть если SourceFormat и DestFormat равны unsigned __int32, указатель функции должен иметь тип void (*)(unsigned __int32, unsigned __int32). Вместо этого вы пытаетесь предоставить функцию, которая принимает аргументы по ссылке, то есть тип указателя - void (*)(unsigned __int32 &, unsigned __int32 &). Это абсолютно нереализованные и несовместимые типы указателей. Следующий простой код не сможет скомпилироваться по той же причине

void foo(int&);
void (*pf)(int) = foo; 
// ERROR: a value of type "void (*)(int &)" cannot be used to initialize an entity of type "void (*)(int)"

Как вы ожидаете, что это сработает? Либо удалите ссылки из фактических параметров функции (используйте вместо этого возвращаемый тип), либо добавьте их в объявление параметров шаблона.

Другая проблема заключается в том, что вы пытаетесь использовать указатели на static функции (внутренняя связь) для параметризации шаблона. Это незаконно в C ++. Короткий пример, иллюстрирующий проблему, может выглядеть следующим образом

template <void (*P)()> void foo() {}
static void bar() {}
...
foo<bar>();
// ERROR: template argument may not reference a non-external entity

Если вы хотите параметризовать шаблон значением указателя, аргумент, который вы предоставляете, должен указывать на сущность с внешней связью. Ваш компилятор может разрешить то, что вы сделали, как есть, но это все еще незаконно.

Наконец, в C ++ запрещено заканчивать определение автономной функции точкой с запятой. На самом деле это рассматривается как «пустое объявление», и в C ++ нет «пустых объявлений». Многие компиляторы допускают это, но это все еще незаконно.

P.S. Кроме того, как уже отмечали другие, вам удалось изменить порядок типов параметров в функции преобразования без шаблонов convertARGB_GREY.

2 голосов
/ 03 февраля 2010

Я не знаю, сделали ли вы это намеренно, но параметры вашего шаблона идут в Source / Destintaion и затем Destination / Source.

Обратите внимание, что когда вы делаете _draw<unsigned __int32, unsigned __int8, &convertARGB_GREY>(...);, ваше определение шаблона заполняет их как:

SourceFormat = unsigned __int32
DestFormat = unsigned __int8
void (*convert)(unsigned __int8, unsigned __int32)

Хотя у вас нет функции этого определения.

У вас есть тот, который соответствует void (*convert)(unsigned __int32&, unsigned __int8&)
Вы видите, как параметры не совпадают?

Объявите ваш шаблон так:

template <
    class SourceFormat,
    class DestFormat,
    void (*convert)(SourceFormat, DestFormat)> 
static void _draw(...);

и ваше объявление функции выглядит так:

void convertARGB_GREY(
    unsigned __int32 source,        // notice how I removed the '&'
    unsigned __int8 destination)    // character on these two lines

и он скомпилируется. (Так как вы потеряете ссылки, я рекомендую вернуть результат в этом случае: unsigned __int8 destination convertARGB_GREY(...) хотя.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...