Мой коллега рассказал мне о небольшом дизайне, который он использовал со своей командой, которая послала мой ум кипения. Это своего рода черт класс, который они могут специализировать в чрезвычайно разобранном виде.Неопределенные методы трюков шаблонов?
Мне было трудно понять, как это может работать, и я все еще не уверен в своей идее, поэтому я подумал, что попрошу о помощи здесь.
Мы говорим о g ++ здесь, в частности версии 3.4.2 и 4.3.2 (похоже, они работают с обоими).
Идея довольно проста:
1- Определить интерфейс
// interface.h
template <class T>
struct Interface
{
void foo(); // the method is not implemented, it could not work if it was
};
//
// I do not think it is necessary
// but they prefer free-standing methods with templates
// because of the automatic argument deduction
//
template <class T>
void foo(Interface<T>& interface) { interface.foo(); }
2- Определение класса, и в исходном файле специализировать интерфейс для этого класса (определение его методы)
// special.h
class Special {};
// special.cpp
#include "interface.h"
#include "special.h"
//
// Note that this specialization is not visible outside of this translation unit
//
template <>
struct Interface<Special>
{
void foo() { std::cout << "Special" << std::endl; }
};
3- Для использования, это просто слишком:
// main.cpp
#include "interface.h"
class Special; // yes, it only costs a forward declaration
// which helps much in term of dependencies
int main(int argc, char* argv[])
{
Interface<Special> special;
foo(special);
return 0;
};
Это неопределенный символ, если единица перевода не определила специализацию Interface
для Special
.
Теперь я бы подумал, что для этого потребуется ключевое слово export
, которое, насколько мне известно, никогда не было реализовано в g ++ (и реализовано только один раз в компиляторе на C++, а его авторы советуют кому-то не делать этого, учитывая время и усилия он их взял).
Я подозреваю, что-то делать с линкера разрешающего методы шаблонов получил ...
- ли вы когда-либо встречал ничего подобного раньше?
- Соответствует ли это стандарту или, по вашему мнению, это удачное совпадение, это работает?
Я должен признать, что я совершенно озадачен конструкт ...
Таким образом, если я правильно понимаю, в «special.h» было бы достаточно включить «interface.h» и переслать объявление специализации шаблона «template <> struct Interface;», а затем в «main.cpp» включить «special.h», чтобы сделать программу корректной, даже если определение метода «Интерфейс :: foo' никогда не появится? –
@Matthieu, точно!Вот как вы можете решить страдания –
Если я прочитал это правильно, это означает, что любая программа (несколько единиц перевода), где существует явная специализация шаблона для заданного набора параметров, но в какой-либо другой единицы перевода неявная специализация используется для один и тот же набор параметров - это нарушение ODR, которое компилятор не требует - и, вероятно, не может - выдать диагностику? Это довольно страшно и еще одна веская причина всегда ставить частичные специализации прямо с основным шаблоном, где это возможно. – Stewart