Подтвердить что ты не робот

Как предотвратить создание неспециализированных шаблонов?

У меня есть шаблонный 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.

4b9b3361

Ответ 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, ... ) будет запускать утверждение все время.