Скажем, у меня есть функция шаблона, которая принимает целое число и константу ссылки на экземпляр типа T. Теперь, в зависимости от целого числа, допустимо только несколько T, иначе исключение выдается во время выполнения.
Если все использования этой функции будут использовать постоянные целые числа, можно было бы сделать int параметром шаблона и использовать статическое утверждение, чтобы проверить, допустимо ли это. Поэтому вместо func(1,c)
можно использовать func<1>(c)
и получить проверку типа компиляции. Есть ли способ написать func(1,c)
и по-прежнему держать проверку времени компиляции, а также писать func(i,c)
и использовать динамическое утверждение? Цель состоит в том, чтобы сделать его прозрачным для разработчика. Было бы здорово добавить эту безопасность, не беспокоя разработчиков о таких вещах, как константы времени компиляции. Вероятно, они только помнят, что func(1,c)
всегда работает и использует это, избегая проверки.
Как я могу определить функцию со статическим утверждением, когда это возможно, и динамическое утверждение иначе?
Следующий код показывает решение для GCC Иван Щербаков:
#include <iostream>
#include <cassert>
template<typename T>
void __attribute__((always_inline)) func(const int& i, const T& t);
void compile_time_error_() __attribute__((__error__ ("assertion failed")));
template<>
void __attribute__((always_inline))
func(const int& i, const float& t)
{
do {
if (i != 0) {
if (__builtin_constant_p(i)) compile_time_error_();
std::cerr << "assertion xzy failed" << std::endl;
exit(1);
}
} while (0);
func_impl<float>(i,t);
}
Это позволит только комбинацию я = 0 и T = float. Для других комбинаций хорошим способом было бы создание макроса, создающего код template<> func(const int& i, const T& t)
с заменой T и я!= 0.