2012-02-05 38 views
1

說我有這樣的計算地圖元素的這樣的總和模板函數:如何測試包含的地圖類型

template <class A, class B> double Total(const map<A, B>& cntr) 
{ 
    map<A, B>::const_iterator iter; 
    double total = 0; 

    for (iter = cntr.begin(); iter != cntr.end(); ++iter) 
     total += iter->second; 

    return total; 
} 

這將做工精細,每當B爲數字類型;然而,很顯然,如果你通過了一個類似map<int, string>的引用,它將無法工作。

我想知道如何測試包含在地圖的非關鍵部分中的類型,以便我可以通過異常或其他東西。我嘗試使用isdigit(),但似乎無法得到一個工作版本。

編輯:我的測試用途是添加功能,以便int類型總是用來計算總數,所以我可以通過map<int, string>map<string, int>,它會一直計算int類型。

+1

我確定編譯器會告訴你'+ ='不適用於double和string。 – 2012-02-05 15:54:44

+0

爲什麼你的返回類型是'double'而不是'B'? – 2012-02-05 15:59:55

+0

對不起,措辭不佳。我沒有具體說明我的用途。編輯。 – bqui56 2012-02-05 16:01:52

回答

2

您可以在C++ 11或boost中使用類型特徵。

#include <type_traits> 

template <class A, class B> double Sum(const map<A, B>& cntr) 
{ 
    static_assert(std::is_arithmetic<B>::value, "Invalid type!"); 
    map<A, B>::const_iterator iter; 
    double total = 0; 

    for (iter = cntr.begin(); iter != cntr.end(); ++iter) 
     total += iter->second; 

    return total; 
} 

請記住,即使沒有聲明,無效的類型也不會編譯。

0

事實上,如果你嘗試用類型參數調用你的代碼,那麼opertor + =(double a,const B & o)是未定義的,所以你在你提到的情況下是安全的。

1

您的代碼太嚴格了,因爲map需要兩個以上的模板參數,並且您還可能希望支持其他類型,如unordered_map。我建議一個模板是這樣的:

template <typename Map> 
typename Map::mapped_type accumulate(Map const & m) 
{ 
    typedef typename Map::mapped_type type; 
    type result; 

    // if you like: 
    static_assert(std::is_arithmetic<type>::value, "Mapped type cannot be accumulated over."); 

    for (auto it = m.cbegin(), end = m.cend(); it != end; ++it) // or your favourte loop construct 
    { 
     result += it->second; 
    } 

    return result; 
} 

其實你可以積累在字符串,也通過串聯,但我已經添加的情況下,爲算術類型的靜態斷言檢查要限制這一點。或者,如果您想將字符串轉換爲數字,則可以編寫一個更通用的「添加」包裝,該字符串使用std::stoulstd::stod

也可以容易地提供非零的起始值。

還或者,整個事情可以表示爲使用std::accumulate一個班輪和拉姆達:

auto result = std::accumulate(m.cbegin(), m.cend(), 0.0, 
    [](double d, Map::value_type const & p) -> double { return d + p.second; }); 
0

那麼,你可以嘗試使用static_cast操作來檢測,如果參數可以澆鑄爲號碼類型。例如,一個功能

template <class T> void func (T arg) { 
    double u = static_cast<double> (arg); 
    //do foo 
} 

如果arg是數字型的不是,編譯器必須執行編譯時間錯誤。

相關問題