Непосредственно приведение от указателя к шаблонной функции? - PullRequest
5 голосов
/ 11 марта 2011

Я пытаюсь взять указатель на экземпляр шаблона функции и привести его к 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
}

Я получаю следующую ошибку (в 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

Почему это происходит?Функция templateFunction (для типа бетона T=int) не перегружена.Можно определить, к какому экземпляру функции я обращаюсь.

Если заменить строку erroneus на:

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

Она компилируется без проблем.

Спасибо!


Обновление:

Когда нормальный указатель void* заменяется на фиктивный указатель на функцию void(*)(), как предложил Джеймс (спасибо), это устраняет ошибку:

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

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

Ответы [ 2 ]

12 голосов
/ 11 марта 2011

Оба технически неверны: в C ++ вы не можете преобразовать указатель функции в void*.

Типы указателя на функцию (например, void (*)(int*) здесь) - это совершенно другой класс типов, чем типы указателя на объект (например, void* здесь).

Visual C ++, разрешающий преобразование вообще (например, в void* addr1 = &plainFunction;), является расширением языка (компиляция с флагом /Za, который отключает расширения языка, приводит к отклонению обеих строк).

Ошибка, конечно, немного вводит в заблуждение, хотя некоторые другие компиляторы также бесполезны (Comeau сообщает об «ошибке: ни один экземпляр шаблона функции« templateFunction »не соответствует требуемому типу»).

6 голосов
/ 11 марта 2011

Компилятор должен выдавать ошибку в обоих случаях.Указатели на функции не могут быть преобразованы в void* в соответствии со Стандартом §4.10 / 2, поскольку функции не являются объектами (§1.8 / 1).Visual Studio 2008 допускает это как расширение, отметьте эту ошибку .

Используйте typedef, чтобы избежать недоразумений:

typedef void(func)(int*); // declare func type
func* addr1 = &plainFunction;         // OK
func* addr2 = &templateFunction<int>; // OK
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...