Сопоставление символов специализации шаблонных функций в разных библиотеках

До сих пор у меня была установка, где определенный шаблон функции getF было объявлено так в заголовках

template <typename T> F* getF();

оставляя тело функции неопределенным. Затем в общей библиотеке, getFимеет некоторые специализации..

template<>
F* getF<int>()
{
  static int r = 42;
  static Finstance(r);
  return &Finstance;
}

template<>
F* getF<float>()
{
  static float r = 3.14159;
  static Finstance(r);
  return &Finstance;
}

Вышесказанное хорошо работает, когда я запускаю клиентский исполняемый файл getF<float>(), компоновщик заменит соответствующие ссылки, и если специализация не существует в библиотеке, то компиляция завершится с ошибкой компоновщика (что было желаемым поведением)

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

template <typename T> F* getF() { return 0; }

Проблема в том, что теперь компилятор будет использовать это определение для всех случаев, независимо от того, есть ли специализация в библиотеке

Вопрос: Есть ли другой способ обеспечить поведение по умолчанию для функции во время выполнения, не перемещая специализации в заголовочные файлы?

2 ответа

Решение

Лучшее решение - объявить о существовании явных специализаций библиотеки.

// All in the same header file:
template <typename T> F* getF() { return 0; }
template <> F* getF<int>();
template <> F* getF<float>();

Это удовлетворяет правилу из стандарта 14.7.3/6:

Если шаблон, шаблон элемента или элемент шаблона класса явно специализированы, то эта специализация должна быть объявлена ​​до первого использования этой специализации, которая вызовет неявную реализацию в каждой единице перевода, в которой такое использование происходит.; Диагностика не требуется.

По сути, вы хотите следующее: "включить особые случаи F, когда T является int или float". Это именно то, о чем говорят такие конструкции, как boost::enable_if и std::enable_if.

Есть тонкие различия в включении / отключении функций по сравнению с классами (классы проще). Смотрите хорошие примеры здесь: boost::enable_if не в сигнатуре функции

Вам может понадобиться некоторая MPL (Boost Meta-Program Library), чтобы выразить "или" часть вашего правила.

Другие вопросы по тегам