Как уже упоминалось в комментарии Alexander C., вы уверены, что компилировать ошибку не подходит?
template <typename T> struct GateKeeper;
// Func we want to call
template <typename S, typename T> void foo (T t);
// Warpper that checks the type and forwards the call
template <typename T> inline void foo (T t)
{
//
// This call will fail for unless a specialization of
// GateKeeper for `T` is defined with a member TYPE
foo< typename GateKeeper<T>::TYPE, T > (t);
}
//
// This declaration "allows" the type int.
template <> struct GateKeeper<int> { typedef int TYPE; };
void bar()
{
foo (0); // Compiles
foo (0.0); // Causes error in wrapping foo
}
Частичная специализация может быть использован для разрешения любой специализации данного шаблона:
// Some template type
template <typename T>
class TmplType
{
};
// This allows for specializations of TmplType
template <typename T> struct GateKeeper< TmplType<T> > { typedef int TYPE; };
void bar()
{
TmplType<char> tt;
foo (tt); // Compiles
}
Для каждого типа, который вы хотите, чтобы поддержать вас добавить новую специализацию.
UPDATE: Что происходит:
Примечание: Я изменил имена параметров шаблона из оригинальной версии, чтобы сделать вещи немного яснее.
Когда компилятор видит вызов foo(x)
, единственная функция, которую он может правильно выбрать, - foo<T>(T)
. Это связано с тем, что он не может выводить все параметры шаблона для foo<S,T>(T)
.
Тело foo<T>(T)
направляет вызов к реальной функции:
foo< typename GateKeeper<T>::TYPE, T > (t);
(ASIDE: см here для описания, когда использовать TypeName)
Это делает 2 вещи сразу.
Первый заключается в предоставлении двух параметров шаблона (S и T), которые необходимы для вызова другой функции.
Второй должен использовать элемент GateKeeper<T>
как этот другой тип. Тип GateKeeper<T>
должен быть полным и иметь этот элемент. Именно эта проверка, что позволяет определить, какие типы мы хотим разрешить и которые мы не делаем:
template <typename T> struct GateKeeper; // Incomplete
template <> struct GateKeeper<int> { typedef int TYPE; }; // Complete
Как мы только при условии определения для GateKeeper<int>
и не GateKeeper<double>
, вызов foo(0)
работает правильно, и foo(0.0)
с ошибкой компиляции.
Чтобы double
, нам просто нужно добавить явную специализацию для него:
template <> struct GateKeeper<double> { typedef int TYPE; }; // double now works.
http://www.boost.org/doc/libs/1_45_0/libs/utility/enable_if.html – Anycorn
Бросив исключения - это время выполнения, вывод аргумента шаблона - это время компиляции. Вы действительно хотите сделать это вместо, например. инициирование ошибки компилятора? –
Вы не можете частично специализировать шаблоны функций. Частично специализированные шаблоны могут быть только частично. То, что выглядит как частично специализированные шаблоны функций, - это фактически перегруженные функции. –