为我自己的函数执行通常的算术转换
Performing the usual arithmetic conversions for my own function?
这是今天工作中提出的,所以我想我会把它扔给社区。
一位同事编写了以下代码(或多或少(:
#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 + 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);
}
现在,我可以浏览并为每对整数类型添加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;
}
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;
}
并像使用它一样使用
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);
在 C++11 之前我不知道有什么好方法,但现在你可以做这样的事情。
template<class T, class U>
auto myMax(T&& t, U&& u) -> decltype(t + u)
{
return t < u ? u : t;
}
decltype(t + u)
只是计算出算术表达式中T
和U
的通用类型是什么,并将其用作模板的返回类型。
- 在c++中为我自己的基于指针的数组分配内存的正确方法
- 将矩阵乘以我自己的输入的向量
- 如何正确包含我自己的标头?
- 如何使用我构建的库,而不会从源代码出错,但不为我自己的项目编译?
- 预期'while'或预期'}' 之前回答是,但我自己无法修复
- 为什么__builtin_popcount比我自己的比特计数功能慢?
- 在wxWidgets的事件中包含我自己的数据的最佳方法是什么?
- 如何在我自己的staticLib中使用staticLib
- 在我自己的堆栈中实现top的问题
- 我需要静态转换我的数字模板值吗
- 尝试检查输入的文本与我自己的自定义答案
- 如何在我自己的类中重载"+"和"<<"运算符
- C++:我自己类的动态数组
- 如何在 C++ 中使用我自己的类中的库?
- 如何链接我自己的 .so 文件而不是操作系统捆绑包 .so 文件?
- 如何构建默认使用我自己的构建libc ++的clang?
- 访问另一个类(系统)的非静态字段,就好像它是我自己的字段一样 - 优雅地
- 分发我自己的程序的几个问题
- 为我自己的函数执行通常的算术转换
- 如何将列表'node_ptr'转换为我自己的节点类型