Допустим, у меня есть шаблонная функция, которая принимает целое число и константную ссылку на экземпляр типа 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);
}
Это позволит только комбинацию i=0 и T=float. Для других комбинаций хорошим способом было бы создание макроса, который создает код template<> func(const int& i, const T& t)
с заменой T и i != 0.