Как обеспечить использование специализированной специализации?

Я пытаюсь, чтобы моя функция шаблона выдавала ошибку времени компиляции, если создается неспециализированная базовая версия. Я попробовал обычный шаблон утверждения времени компиляции (отрицательный размер массива), но компиляция не срабатывает, даже когда шаблон не создается. Любые мысли о том, как заставить его терпеть неудачу тогда и только тогда, когда создается функция базового шаблона?

template<class Foo> void func(Foo x) {
  // I want the compiler to complain only if this function is instantiated.
  // Instead, the compiler is complaining here at the declaration.
  int Must_Use_Specialization[-1];
}

template<> void func(int x) {
  printf("Hi\n");
}

Ответ 1

Не определено это самое простое решение:

template<class Foo> void func(Foo x);

template<> void func(int x) {
  printf("Hi\n");
}

Вы также можете определить их в файлах CPP и использовать это, которые будут работать.

И статический метод assert:

template<class Foo> void func(Foo x) {
  static_assert(sizeof(Foo) != sizeof(Foo), "func must be specialized for this type!");
}

Ответ 2

В С++ 11 вы можете использовать static_assert следующим образом:

template<typename T> struct fake_dependency: public std::false_type {};
template<class Foo> void func(Foo x) {
   static_assert(fake_dependency<Foo>::value, "must use specialization");
}

Структура fake_dependency необходима, чтобы сделать утверждение зависимым от вашего параметра шаблона, поэтому он ждет с оценкой, пока не будет создан экземпляр шаблона. Вы также можете исправить свое решение следующим образом:

template<class> struct fake_dependency { enum {value = -1 }; };

template<class Foo> void func(Foo x) {
    int Must_Use_Specialization[fake_dependency<Foo>::value];
}

См. также здесь для живой демонстрации.

Ответ 3

Вы должны сделать это зависимым от Foo, например:

int Must_Use_Specialization[-sizeof(Foo)];

Ответ 4

Вам не нужен базовый шаблон, если вы его никогда не будете использовать! Просто предоставьте перегрузки для типов, которые вы хотите использовать!

void func(int x) {
    printf("Hi 1\n");
}

void func(double x) {
    printf("Hi 2\n");
}

void func(Bar x) {
    printf("Hi 3\n");
}

Это даст вам ошибку времени компиляции для func(foo); (если foo не конвертируется в один из других типов).

Ответ 5

Просто используйте Boost.StaticAssert

(Edit: или static_assert, если у вас есть поддержка С++ 11. Я забыл об этом).