由于范围有限,比较总是假的...有模板

dar*_*roo 6 c++ templates warnings

我有一个模板化函数,它对模板类型变量进行操作,如果该值小于0,则将其设置为0.这样可以正常工作,但是当我的模板化类型未签名时,我会收到有关如何比较总是的警告假.这显然是有道理的,但由于它是模板化的,我希望它对所有数据类型(有符号和无符号)都是通用的,而不是发出警告.

我在Linux上使用g ++,并且我猜测有一种方法可以通过g ++的命令行选项来抑制该特定警告,但我仍然希望在其他非模板化的情况下得到警告.我想知道在代码中是否有某种方法可以防止这种情况,而无需编写多个版本的函数?

template < class T >
T trim(T &val)
{
  if (val < 0)
  {
    val = 0;
  }
  return (val);
}
int main()
{
  char cval = 5;
  unsigned char ucval = 5;

  cout << "Untrimmed: " << (int)cval;
  cval = trim(cval);
  cout << " Trimmed: " << (int)cval << endl;

  cout << "Untrimmed: " << (int)ucval;
  cval = trim(ucval);
  cout << " Trimmed: " << (int)ucval << endl;

 return (0);
}
Run Code Online (Sandbox Code Playgroud)

小智 6

#include <algorithm>

template<class T>
T& trim(T& val) {
  val = std::max(T(0), val);
  return val;
}
Run Code Online (Sandbox Code Playgroud)

通过非const引用传递的问题并不明显.您可以更改上面的返回值(void),按值传递并按值返回,或者传递const&并按值返回:

template<class T>
T trim(T const& val);

// example use:
value = trim(value); // likely the most clear solution
Run Code Online (Sandbox Code Playgroud)

虽然超出了你的问题的范围,但概括一点:

template<class T>
T constrain(T const& value, T const& lower, T const& upper) {
  // returns value if value within [lower, upper] (inclusive end points)
  // returns lower if value < lower
  // otherwise returns upper
  assert(lower <= upper); // precondition
  return std::min(std::max(value, lower), upper);
}

template<class T>
T constrain_range(T const& value, T const& lower, T const& upper) {
  // returns value if value within [lower, upper) (exclusive upper)
  // returns lower if value < lower
  // otherwise returns upper - 1
  assert(lower < upper); // precondition
  if      (value <  lower) return lower;
  else if (value >= upper) return upper - 1;
  else                     return value;
}
Run Code Online (Sandbox Code Playgroud)


Kor*_*icz 5

对于简单的案例,您可以更好地了解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>() );
}
Run Code Online (Sandbox Code Playgroud)

请注意,这is_signedfalse_type浮点数(不要问为什么).要使上述代码与浮点一起使用,您需要输入另一个特征,例如

typedef std::tr1::integral_constant< bool, 
            std::tr1::is_signed<T>::value || 
            std::tr1::is_floating_point<T>::value > has_sign;
Run Code Online (Sandbox Code Playgroud)

...是的,你进入元编程的深度越深,它就会变得如此......忽视这个解决方案并与Roger列出的简单解决方案一致:P.