我有一个模板化函数,它对模板类型变量进行操作,如果该值小于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);
}
答案 0 :(得分:6)
#include <algorithm>
template<class T>
T& trim(T& val) {
val = std::max(T(0), val);
return val;
}
通过非const引用传递的问题并不明显。您可以更改上面的返回值(void),按值传递并按值返回,或者通过const&amp;并按价值返回:
template<class T>
T trim(T const& val);
// example use:
value = trim(value); // likely the most clear solution
Generalize多一点,即使超出了你的问题的范围:
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;
}
答案 1 :(得分: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>() );
}
请注意,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;
...是的,你进入元编程的深度越大,它变得更加丑陋......忽视这个解决方案,并选择Roger列出的简单方法:P。
答案 2 :(得分:2)
用于取消警告的编译器标志为gcc的-Wno-type-limits
。
答案 3 :(得分:1)
通过将生成警告的每个比较转换为虚拟函数,可以逐个抑制所有类型的 -Wtype-limits 警告,该函数接受比较中使用的两个操作数和返回操作数比较的结果。 例如,原始问题中的 trim()函数可以转换为:
// Dummy function for -Wtype-limits warnings suppression.
template < class T >
static inline dummy_less(const T &a, const T &b)
{
return (a < b);
}
template < class T >
T trim(T &val)
{
if (dumy_less(val, 0))
{
val = 0;
}
return (val);
}