开发者

Error with using a function as a non-type template parameter

开发者 https://www.devze.com 2022-12-18 20:13 出处:网络
I have this template : template <class SourceFormat, class DestFormat, void (*convert)(DestFormat, SourceFormat)>

I have this template :

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

And these functions :

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

I use the template in another function :

    void Blitter::draw(...) {

    if (...) {
        _draw<unsig开发者_Go百科ned __int32, unsigned __int32, &convertNone>(...);
    } else {
        _draw<unsigned __int32, unsigned __int8, &convertARGB_GREY>(...); // ERRORS go here!
    }
}

I get these errors :

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

I suppose it's rather obvious that I don't fully comprehend functions-as-parameters... :-(

Many thanks in advance


There are several problems in your code.

In your code, when you call _draw, the SourceFormat and DestFormat parameters of _draw template are supplied with explicit arguments. These arguments are plain non-reference integer types. That automatically means that the third template parameter of _draw is supposed to be a function that takes its arguments by value as well. I.e. if SourceFormat and DestFormat is unsigned __int32, then the function pointer should have type void (*)(unsigned __int32, unsigned __int32). Instead, you are trying to supply a function that takes its arguments by reference, i.e. the pointer type is void (*)(unsigned __int32 &, unsigned __int32 &). These are completely unrealted and incompatibe pointer types. The following simple code would fail to compile for the same reason

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)"

How do you expect this to work? Either remove references from actual function parameters (use return type instead), or add them in template parameter declaration.

Another problem is that you are trying to use pointers to static functions (internal linkage) to parametrize a template. This is illegal in C++. A short example that illustrates the problem might look as follows

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

If you want to parametrize a template with a pointer value, the argument you supply must point to an entity with external linkage. You compiler might allow what you did as is, but it is still illegal.

Finally, it illegal in C++ to end a standalone function definition with semicolon. This is treated as an "empty declaration" actually and there are no "empty declarations" in C++. Many compilers allow this, but it is still illegal.

P.S. Additionally, as others already noted, you managed to reverse the order of parameter types in your non-template converter function convertARGB_GREY.


I don't know if you've done it intentionally, but your template parameters go Source/Destintaion and then Destination/Source.

Notice that when you do _draw<unsigned __int32, unsigned __int8, &convertARGB_GREY>(...); your template definition fills them in as:

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

You don't have a function of that definition though.

You do have one that matches void (*convert)(unsigned __int32&, unsigned __int8&)
Do you see how the parameters don't match?

Declare your template like this:

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

and your function declaration like this:

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

and it will compile. (Since you lose the references, I'd recommend returning the result in this case: unsigned __int8 destination convertARGB_GREY(...) though.)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号