有個需求,能否做到實現一個類似這樣的函數:
template <typename T1, typename T2>
XXX Min(T1 t1, T2 t2)
{
return (t1 < t2 ? t1 : t2);
}
其中 XXX 是我們要推導出的類型。
以下是一個失敗的嘗試。
我記得 Loki 里有關于如何判斷某個類型能否隱式轉換為另一個類型的東西,大意如下:
template <typename T, typename U>
class Conversion
{
private:
typedef char Small;
class Big { char XXX[2]; };
static Small Test(U);
static Big Test(...);
static T MakeT();
public:
enum
{
Exists = (sizeof(Test(MakeT())) == sizeof(Small)),
};
};
如此,Conversion<T, U>::Exists 就能判斷 T 到 U 的轉換是否存在了。
然后再搞個選擇:
template <bool Condition, typename TypeIfTrue, typename TypeIfFalse>
struct Select
{
typedef TypeIfFalse Type;
};
template <typename TypeIfTrue, typename TypeIfFalse>
struct Select<true, TypeIfTrue, TypeIfFalse>
{
typedef TypeIfTrue Type;
};
最后,再來個:
struct NullType;
template <typename T, typename U>
struct CommonType
{
typedef typename Select<Conversion<T, U>::exists,
U,
typename Select<Conversion<U, T>::exists,
T,
NullType>::Type
>::Type Type;
};
那么 CommonType<T1, T2> 就是 T1 和 T2 之間哪個是他們的共有類型了。
測試:
int main()
{
CommonType<int, double>::Type m = 0;
return 0;
}
調試,確認 m 是 double 的。但是反過來寫 CommonType<double, int>::Type m = 0;,m 卻是 int 的。
這說明這套機制一開始就有問題,Test(U) 和 Test(…) 兩個重載函數中,Test(…) 不會在需要 double 轉 int 時勝出。這是第一個問題。
第二個問題,當寫下如下代碼的時候:
template <typename T1, typename T2>
CommonType<T1, T2>::Type Min(T1 t1, T2 t2)
{
return (t1 < t2 ? t1 : t2);
}
編譯無法通過。原因是返回類型中的 CommonType 中的模板參數 T、U 無法接受此時還不能確定的 T1、T2。
(更正:不是這個原因,返回類型前加 typename 即可。現在問題還是第一個問題。)
請教各位,有沒有什么方法做到?歡迎指教~
C++ 0x 中就能很方便做到了:
template <typename T1, typename T2>
auto Min(T1 t1, T2 t2) -> decltype(t1 + t2)
{
return (t1 < t2 ? t1 : t2);
}
int main()
{
int a = 2;
double b = 1.0;
auto m = Min(a, b);
return 0;
}
posted on 2011-03-29 21:27
溪流 閱讀(1896)
評論(16) 編輯 收藏 引用 所屬分類:
C++