Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Directly casting from pointer to a template function?

Tags:

c++

visual-c++

I am trying to take a pointer to an instance of function template and cast it to void*:

#include <stdio.h>

void plainFunction(int *param) {}

template <typename T>
void templateFunction(T *param) {}

int main() {
    void *addr1=&plainFunction; //OK
    void *addr2=&templateFunction<int>; //Compile error
}

I get the following error (in Visual Studio 2008)

main.cu(10) : error C2440: 'initializing' : cannot convert from 'void (__cdecl *)(T *)' to 'void *'
Context does not allow for disambiguation of overloaded function

Why is it happening? Function templateFunction (for concrete type T=int) is not overloaded. It is possible to deduct which instance of the function I am refering to.

If I replace the erroneus line with:

void (*foo)(int*)=&templateFunction<int>;
void *addr2=foo;

It compiles without a problem.

Thank you!


Update:

When normal pointer void* is replaced by dummy function pointer void(*)(), as suggested by James (thank you), it makes the error go away:

void (*addr1)()=(void(*)())&plainFunction;
void (*addr2)()=(void(*)())(&templateFunction<int>);

However, if the error was caused by casting a function-pointer to a normal pointer, the compiler should complain in both cases. It does not however, so I continue to assume that it is correct at least for this compiler. If I am not mistaken, the standard just says that function pointers don't have to be represented like normal pointers, but it does not forbid that.

like image 238
CygnusX1 Avatar asked Mar 11 '11 19:03

CygnusX1


2 Answers

Both are technically wrong: in C++, you can't convert a function pointer to a void*.

Pointer-to-function types (like void (*)(int*) here) are a completely different class of types than pointer-to-object types (like void* here).

Visual C++ allowing the conversion at all (e.g. in void* addr1 = &plainFunction;) is a language extension (compiling with the /Za flag, which disables language extensions, causes both lines to be rejected).

The error is a bit misleading, for sure, though some other compilers are equally unhelpful (Comeau reports "error: no instance of function template "templateFunction" matches the required type").

like image 144
James McNellis Avatar answered Oct 22 '22 15:10

James McNellis


Compiler should generate error in both cases. Function pointers are not convertible to void* according to the Standard §4.10/2 since functions are not objects (§1.8/1). Visual Studio 2008 allows this as an extension, check this bug.

Use typedef to avoid misunderstanding:

typedef void(func)(int*); // declare func type
func* addr1 = &plainFunction;         // OK
func* addr2 = &templateFunction<int>; // OK
like image 40
Kirill V. Lyadvinsky Avatar answered Oct 22 '22 15:10

Kirill V. Lyadvinsky