Как предотвратить создание узкоспециализированных шаблонов? - PullRequest
36 голосов
/ 15 августа 2011

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

Ответы [ 3 ]

41 голосов
/ 15 августа 2011

Только не определяйте класс:

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;
}

Почему это работает?Просто потому, что не какой-либо универсальный шаблон.Объявлено, да, но не определено.

19 голосов
/ 15 августа 2011

Вы можете просто не определять базовый вариант:

template <typename> class Foo;             // no definition!

template <> class Foo<int> { /* ... */ };  // Foo<int> is OK
16 голосов
/ 15 августа 2011

Трюк для C ++ 0x (также доступен с эмуляцией C ++ 03 static_assert, но сообщение об ошибке не обязательно лучше, чем оставить основной шаблон неопределенным):

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

...