为我自己的函数执行通常的算术转换?

时间:2012-05-16 21:19:43

标签: c++

今天就出现了,所以我想我会把它扔给社区。

一位同事编写了以下代码(或多或少):

#include <algorithm>

double chop(double x) {
    return std::max(0, x);
}

但是这甚至都没有编译,因为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);
}

这个编译!但它产生了相当令人惊讶的结果,x等于0.25。我不确定他找到问题需要多长时间,甚至在找到问题之后,他不得不问为什么它不起作用。

我的回答是(a)使用0.0而不是0(修复了错误),(b)使用std::max代替myMax(当你考虑它时,它的行为非常可怕)

但他想知道为什么会这样。我的意思是,他可以写0 + x0 * x0 - 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);
}

现在,我可以为每对整数类型添加WiderType的特化,再添加一些其他常用算术转换。 (我想我可以将其重命名为UsualConversions或其他一些。)

但有更简单的方法吗?也就是说,C ++语言是否为我提供了一种简单的方法来定义我自己的函数,该函数在其参数上执行与各种内置算术运算符相同的转换?

2 个答案:

答案 0 :(得分:7)

除了Charles Bailey的回答,你也可以这样做:

template<typename T1, typename T2>
typename std::common_type<T1, T2>::type max(T1&& a, T2&& b) {
    return a < b ? b : a;
}

common_type中有一个typedef type,它是两种类型都可以隐式转换为的类型,例如,如果它是doubleint ,它会返回double,但如果是intint,则会返回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;
}

并像

一样使用它
double d;
max(0, 43.12, d);

虽然必须以这种方式声明变量,但这非常笨拙。如果你觉得它更漂亮,你也可以这样做:

template<typename RetType, typename T1, typename T2>
RetType max(const T1& a, const T2& b) {
    return a < b ? b : a;
}

然后

return max<double>(0, 43.11);

答案 1 :(得分:4)

我不知道在C ++ 11之前有一个好方法,但现在你可以做这样的事情。

template<class T, class U>
auto myMax(T&& t, U&& u) -> decltype(t + u)
{
    return t < u ? u : t;
}

decltype(t + u)只计算TU的常见类型在算术表达式中的含义,并将其用作模板的返回类型。

相关问题