Ответ 1
Я попытался бы избежать static_assert, используя что-то вроде
template<typename T> FormatB getFormat()=delete;
Затем авторы компилятора могут улучшить эти сообщения об ошибках.
У меня есть две библиотеки, с которыми я работаю, и для удобства я написал конвертер между некоторыми типами/структурами, которые они используют.
template<typename T>
struct unsupportedType : std::false_type
{};
template<typename T>
FormatB getFormat()
{
static_assert(
unsupportedType<T>::value, "This is not supported!");
}
template<>
FormatB getFormat<FormatA::type1>()
{
return FormatB(//some parameters);
}
template<>
FormatB getFormat<FormatA::type2>()
{
return FormatB(//some other parameters);
}
Теперь из-за структуры unsupportedType
компилятор не сразу видит, что утверждение всегда терпит неудачу и, таким образом, не вызывает ошибку компиляции, если не-специализированная версия не называется где-то. Однако компилятор также не знает, что оператор return после static_assert
не нужен. Я не просто хочу разместить произвольное выражение return после утверждения, чтобы избавиться от предупреждения.
Вопрос: Что такое чистый способ избавиться от предупреждения?
Я попытался бы избежать static_assert, используя что-то вроде
template<typename T> FormatB getFormat()=delete;
Затем авторы компилятора могут улучшить эти сообщения об ошибках.
Существует более одного способа выхода из функции, return
ing - один, но throw
ing - это другое:
template<typename T>
FormatB getFormat()
{
static_assert(
unsupportedType<T>::value, "This is not supported!");
throw 0; // Unreachable
}
Как вы сказали в комментарии к принятому ответу, что он фактически не отвечает на вопрос напрямую, вот рабочее решение, которое может помочь будущим читателям.
Чтобы решить эту проблему, вы можете просто определить свой шаблон функции следующим образом:
template<typename T, typename R = void>
R getFormat()
{
static_assert(
unsupportedType<T>::value, "This is not supported!");
}
Никаких изменений не требуется для других специализаций, тип R
может быть выведен непосредственно из возвращаемого типа.
Это следует за минимальным рабочим примером, показывающим, как он работает:
#include<type_traits>
template<typename T>
struct unsupportedType : std::false_type
{};
struct FormatA{
using type1 = int;
using type2 = char;
};
struct FormatB{};
template<typename T, typename R = void>
R getFormat()
{
static_assert(
unsupportedType<T>::value, "This is not supported!");
}
template<>
FormatB getFormat<FormatA::type1>()
{
return FormatB();
}
template<>
FormatB getFormat<FormatA::type2>()
{
return FormatB();
}
int main() {}
Вы можете использовать GCC __builtin_unreachable
(это путь вниз по этой ссылке), чтобы сообщить компилятору, что данная строка недоступна, который будет подавлять это предупреждение. (В основном я упоминаю это для C-разработчиков, которые здесь, для С++, метод, использующий delete
выше, лучше).