Сценарий в вашем примере очень редкий и связан с определенным правилом шаблона, связанным конкретно с функциями и массивом.
Для уточнения, если у вас есть шаблонная функция, которая берет другую функцию по ссылке, тогда тип, выведенный для T, является фактическим типом функции (не указателем на функцию).
Например,
template<typename T>
void fun(const T& f);
{
.....
}
void print(int);
fun(print); //for this case T will be deduced as void(int) and not void(*)int i.e. T will not be a function pointer
Таким образом, чтобы ваш пример работал на эталонный пример, вам нужно создать еще одну специализацию шаблона, например:
template <typename R, typename... TArgs>
struct func_traits<R(TArgs...)> {
static constexpr uint32_t ARG_COUNT = sizeof...(TArgs);
}; //note (*) is removed from template function
Короче говоря, если вы передаете функцию или массив по значению, они распадаются на указатель, но если вы передаете по ссылке, то они обрабатываются как есть.
Более подробная информация доступна в Scott Meyers Effective Modern C ++ (https://www.oreilly.com/library/view/effective-modern-c/9781491908419/ch01.html)