В проекте есть семейство шаблонных функций которые принимают аргументы с некоторым ожидаемым интерфейсом. Примерно так:
template<typename T>
void do_some(...)
{
//...
const auto c = T::some();
//...
}
template<typename T>
void do_other(...)
{
//...
const auto o = T::other();
//...
}
Так вот, требуется для некоторых специализаций запретить вызов T::other() и выводить ошибку компиляции в этом месте.
Первое решение это просто не делать объявление other для нужной специализации T, но тогда компилятор будет выводить ошибку об отсутствии other и не понятно что делать. Хотелось бы выводить нечто вразумительное чтобы было понятно, что вызов other для данного T запрещен, а не что его забыли.
Второе решение - использовать static_assert, вот так:
int Spec::other()
{
static_assert(false, "you must not call `other` func");
}
Но тогда ошибка выводится всегда когда компилятор встречает определение Spec::other, а не в месте ее вызова в do_other. Как выводить ошибку когда требуется?
Объявить "неправильные" специализации other как = delete явным образом. Явное = delete - это как раз способ выразить то, что специализацию не "забыли", а умышленно запретили.
Есть еще хитрость, если все ж таки нужно выводить осмысленное сообщение об ошибке. Заключается она в том чтобы сделать Spec::other шаблоном, вот так например:
template<typename _dummy = int>
int Spec::other()
{
static_assert(false, "Do not call `Spec::other` func");
return -1;
}
В таком случае static_assert будет срабатывать при инстанцировании Spec::other, то есть в месте ее вызова. Даже несмотря на то, что параметр шаблона имеет значение по-умолчанию.
Продвижение своими сайтами как стратегия роста и независимости