C-обратный вызов для шаблона функции: явное создание экземпляра шаблона

Предпосылка

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

void register_callback(void* f, void* data);
void invoke_callback();

Проблема

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

template  void my_callback(void* data) { … }

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

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

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

 "void my_callback  (void *)", ссылка на которую имеется:
  _main в ccYLXc5w.o
 

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

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

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

template void my_callback(void* data);

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

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

int main() {
    int ft = 42;
    do_register_callback(ft);
    invoke_callback();
}

Второе «решение»

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

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

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

Вопрос

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

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

Дополнительный вопрос

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

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

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

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

14
задан Konrad Rudolph 18 July 2011 в 14:57
поделиться