Как предотвратить создание неспециализированных шаблонов?
У меня есть шаблонный class
(назовите его Foo
), который имеет несколько специализаций. Я хочу, чтобы компиляция завершилась неудачей, если кто-то попытается использовать неспециализированную версию Foo
.
Вот что я на самом деле:
template <typename Type>
class Foo
{
Foo() { cannot_instantiate_an_unspecialized_Foo(); }
// This method is NEVER defined to prevent linking.
// Its name was chosen to provide a clear explanation why the compilation failed.
void cannot_instantiate_an_unspecialized_Foo();
};
template <>
class Foo<int>
{ };
template <>
class Foo<double>
{ };
Итак, чтобы:
int main()
{
Foo<int> foo;
}
Работает в то время как:
int main()
{
Foo<char> foo;
}
Нет.
Очевидно, что цепочка компилятора только жалуется, когда происходит процесс связывания. Но есть ли способ заставить его жаловаться раньше?
Я могу использовать boost
.
Ответы
Ответ 1
Просто не определяйте класс:
template <typename Type>
class Foo;
template <>
class Foo<int> { };
int main(int argc, char *argv[])
{
Foo<int> f; // Fine, Foo<int> exists
Foo<char> fc; // Error, incomplete type
return 0;
}
Почему это работает? Просто потому, что нет никакого общего шаблона. Объявлено, да, но не определено.
Ответ 2
Вы просто не можете определить базовый случай:
template <typename> class Foo; // no definition!
template <> class Foo<int> { /* ... */ }; // Foo<int> is OK
Ответ 3
Трюк для С++ 0x (также доступен с эмуляцией С++ 03 static_assert
, но сообщение об ошибке не обязательно лучше, чем оставить основной шаблон undefined):
template<typename T>
struct dependent_false: std::false_type {};
template<typename Type>
struct Foo {
static_assert( dependent_false<Type>::value
, "Only specializations of Foo may be used" );
};
Утверждение запускается только тогда, когда Foo
создается с помощью первичного шаблона. Использование static_assert( false, ... )
будет запускать утверждение все время.