@Matthieu, @zennehoy - ой - да - спасибо!

ка

Я использую библиотеку C (из C ++), которая обеспечивает следующий интерфейс:

void register_callback(void* f, void* data);
void invoke_callback();
проблема

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

template <typename T> void my_callback(void* data) { … }

int main() {
    int ft = 42;
    register_callback(reinterpret_cast<void*>(&my_callback<int>), &ft);
    invoke_callback();
}

Это дает мне следующую ошибку компоновщика (при использовании g ++ (GCC) 4.5.1 на OS Xно работает на большинстве других комбинаций версии компилятора / платформы):

Неопределенные символы для архитектуры x86_64:

"void my_callback<int>(void*)", referenced from:  
  _main in ccYLXc5w.o

что я нахожу понятным.

Первое «решение»

Это легко исправить, явно создав экземпляр шаблона:

template void my_callback<int>(void* data);

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

template <typename T>
void do_register_callback(T& value) {
    register_callback(reinterpret_cast<void*>(my_callback<T>), &value);
    // Other things …
}

int main() {
    int ft = 42;
    do_register_callback(ft);
    invoke_callback();
}
Второе «решение»

Шаблон функции неявно создается путем вызова функции. Итак, давайте сделаем это, но убедитесь, что вызов на самом деле не выполняется (функция имеет побочные эффекты):

template <typename T>
void do_register_callback(T& value) {
    if (false) { my_callback<T>(0); }
    register_callback(reinterpret_cast<void*>(my_callback<T>), &value);
}

Этоткажется работать даже с включенной оптимизацией (чтобы компилятор удалял мертвую ветку). Но я не уверен, что это когда-нибудь не сломается. Я также считаю, что это очень уродливое решение, которое требует подробного пояснительного комментария, чтобы какой-нибудь будущий сопровождающий удалил этот явно ненужный код.

Вопрос

Как создать экземпляр шаблона, для которого я не знаю аргументов шаблона? Этот вопрос явно бессмысленен: я не могу. - Но есть ли хитрый способ обойти это?

За исключением этого,мой обходной путь гарантированно будет успешным?

Бонусный вопрос

Код (в частности, тот факт, что я приведу функцию указатель наvoid*) также выдает следующее предупреждение:

ISO C ++ запрещает приведение между указателем на функцию и указателем на объект

при компиляции с-pedantic, Могу ли я как-то избавиться от предупреждения,без написания строго типизированной оболочки C для библиотеки (что невозможно в моей ситуации)?

Запуск кода на Ideone (с добавленным приведением для компиляции)

Ответы на вопрос(3)

Ваш ответ на вопрос