今天就出现了,所以我想我会把它扔给社区.
一位同事编写了以下代码(或多或少):
#include <algorithm>
double chop(double x) {
return std::max(0, x);
}
Run Code Online (Sandbox Code Playgroud)
但是这甚至都没有编译,因为它std::max希望它的两个参数具有完全相同的类型.我相信这是如此,它可以采取一对引用并返回一个引用,如果你在用户定义的类型上调用它,很可能是你想要的.很公平.
当然,修复是使用std::max(0.0, x).
现在忍受我一会儿,因为我撒了谎.我的同事实际写的是这样的:
// Included from a very old header file written by someone long gone
template<class T1, class T2>
inline T1 myMax(T1 x, T2 y) {
return (x < y) ? y : x;
}
double chop(double x) {
return myMax(0, x);
}
Run Code Online (Sandbox Code Playgroud)
这编译!但它产生了相当令人惊讶的结果,x等于0.25.我不确定他找到问题需要多长时间,甚至在找到问题之后,他不得不问为什么它不起作用.
我的回答是(a)使用0.0而不是0(修正了bug),以及(b)使用std::max而不是myMax(当你考虑它时,它的行为非常可怕).
但他想知道为什么会这样.我的意思是,他可以写0 + x或0 * x或者0 - x,为什么不myMax(0, x)?
这是我第一次给他他想要的东西:
// this is from the .hh file
// template meta-program to compute the "wider" of two types given as argument
template<class T1, class T2>
struct WiderType {
};
// Partial specialization for case where both types are same
template<class T>
struct WiderType<T, T> {
typedef T type;
};
// Specialization for first type "int" and second type "double"
template<>
struct WiderType<int, double> {
typedef double type;
};
template<class T1, class T2>
inline typename WiderType<T1,T2>::type
myMax(T1 a, T2 b) {
return ((a < b) ? b : a);
}
// this is from the .cc file
double chop(double x) {
return myMax(0, x);
}
// just to show this still works
int chop(int x) {
return myMax(0, x);
}
Run Code Online (Sandbox Code Playgroud)
现在,我可以通过WiderType为每对整数类型添加一个特化,再加上一些用于其他常用算术转换.(我想我可以重命名它UsualConversions或者某些东西.)
但是有更简单的方法吗?也就是说,C++语言是否为我提供了一种简单的方法来定义我自己的函数,该函数在其参数上执行与各种内置算术运算符相同的转换?
除了Charles Bailey的回答,你也可以这样做:
template<typename T1, typename T2>
typename std::common_type<T1, T2>::type max(T1&& a, T2&& b) {
return a < b ? b : a;
}
Run Code Online (Sandbox Code Playgroud)
common_type有一个typedef type它是两种类型可以隐式转换到,所以如果是这样,比如类型,double并且int,它会返回double,但如果它是int和int,它会返回一个int.
如果你根本不能使用C++ 11,那么我唯一能想到的是:
template<typename T1, typename T2, typename T3>
void max(const T1& a, const T2& b, T3& dst) {
dst = a < b ? b : a;
}
Run Code Online (Sandbox Code Playgroud)
并使用它
double d;
max(0, 43.12, d);
Run Code Online (Sandbox Code Playgroud)
不过必须以这种方式声明变量是非常笨拙的.如果你认为它更漂亮,你也可以这样做:
template<typename RetType, typename T1, typename T2>
RetType max(const T1& a, const T2& b) {
return a < b ? b : a;
}
Run Code Online (Sandbox Code Playgroud)
然后
return max<double>(0, 43.11);
Run Code Online (Sandbox Code Playgroud)