CSDN上看到有人问能否实现一个效率较高的max函数,效率接近于宏,于是自动动手写了一个。
由于max宏在判断不同类型时,能够返回大的那个类型(表示范围大),所以只能使用模板来进行返回类型的推导。
在VC8上打开O2或Ox优化选项,测试结果是与宏效率相等。
全部实现如下:
#include <typeinfo>
#include <cassert>
#include <windows.h>
#include <iostream>
template <class T, class U, bool B>
struct BigType
{
typedef T result;
};
template <class T, class U>
struct BigType<T, U, false>
{
typedef U result;
};
template <class T, class U>
struct Type
{
typedef typename BigType<T, U, (sizeof(T) > sizeof(U))>::result BigType;
};
template <class T>
struct Type<T, double>
{
typedef double BigType;
};
template <class T>
struct Type<double, T>
{
typedef double BigType;
};
template <class T>
struct Type<T, float>
{
typedef float BigType;
};
template <class T>
struct Type<float, T>
{
typedef float BigType;
};
template <>
struct Type<double, float>
{
typedef double BigType;
};
template <>
struct Type<float, double>
{
typedef double BigType;
};
template <class T, class U>
typename Type<T, U>::BigType MaX (const T& t, const U& u)
{
typedef typename Type<T, U>::BigType ResultType;
return ResultType(t > u ? t : u); // 原为return (ResultType)t > u ? t : u;
}
int main ()
{
assert (typeid(MaX(1, 2)) == typeid(int));
assert (MaX(1, 2) == 2);
assert (typeid(MaX(1, 2.5)) == typeid(double));
assert (MaX(1, 2.5) == 2.5);
assert (typeid(MaX(1, (float)2.5)) == typeid(float));
assert (MaX(1, (float)2.5) == 2.5);
assert (typeid(MaX((double)2, (float)2.5)) == typeid(double));
assert (MaX((double)2, (float)2.5) == 2.5);
assert (typeid(MaX((long)2, (float)2.5)) == typeid(float));
assert (MaX((long)2, (float)2.5) == 2.5);
assert (typeid(MaX((long)2, (short)2)) == typeid(long));
assert (MaX((long)2, (short)2) == 2);
assert (typeid(MaX((float)2, (__int64)2)) == typeid(float));
assert (MaX((float)2, (__int64)2) == 2);
assert (std::string("hello") < "world");
assert (typeid(MaX(std::string("hello"), "world")) == typeid(std::string));
assert (MaX(std::string("hello"), "world") == "world");
assert (typeid(MaX(std::string("world"), "hello")) == typeid(std::string));
assert (MaX(std::string("hello"), "world") == "world");
// 测试数,需定义在循环外,防止编译器优化掉无意义的循环
__int64 test = 0;
long start = GetTickCount();
for (int i=0; i<1000000000; ++i)
{
test += MaX(i, (__int64)i);
}
// test必须被使用,否则编译器视为无用数据,会被优化掉
std::cout << test << std::endl;
std::cout << (GetTickCount() - start) << std::endl;
test = 0;
start = GetTickCount();
for (int i=0; i<1000000000; ++i)
{
test += max(i, (__int64)i);
}
std::cout << test << std::endl;
std::cout << (GetTickCount() - start) << std::endl;
return 0;
}