Для представленного простого случая вам, безусловно, будет лучше решение, представленное Roger Pate .
Для общего решения метапрограммирования вам нужно: type_traits . Вы можете использовать либо те, что от Boost, либо те, которые поставляются с вашим STL, если они достаточно современны.
namespace detail {
template < class T >
T trim_impl(T &val, const std::tr1::true_type& )
{
if (val < 0)
{
val = 0;
}
return (val);
}
template < class T >
T trim_impl(T &val, const std::tr1::false_type& )
{
return (val);
}
} // end namespace detail
template < class T >
T trim(T &val)
{
return detail::trim_impl( val, std::tr1::is_signed<T>() );
}
Обратите внимание, что is_signed
равно false_type
для чисел с плавающей запятой (не спрашивайте, почему). Чтобы приведенный выше код работал с плавающими точками, вам необходимо ввести другую черту, например
typedef std::tr1::integral_constant< bool,
std::tr1::is_signed<T>::value ||
std::tr1::is_floating_point<T>::value > has_sign;
... и да, чем глубже вы погружаетесь в метапрограммирование , тем страшнее оно становится ... пренебрегайте этим решением и используйте простое, перечисленное Роджером: P.