2016-04-15 196 views
1

我正在使用模板函數searchByCriteria<T>,我希望能夠使用stringdouble運行該函數。我有一個具有stringdouble屬性的自定義對象的列表,我希望能夠使用此函數檢查(由用戶輸入的任何類型的)標準值,以檢查對象中的匹配相同類型的屬性。C++ - 將模板類型對象轉換爲特定數據類型

I.e.用戶輸入一個double值,檢查對象集合是否匹配double值。用戶輸入一個字符串值,檢查對象集合是否匹配字符串值。

我遇到的問題是一旦輸入值,它將被傳遞給另一個模板函數,以便根據列表中的元素進行檢查。此時,作爲參數傳遞的T對象需要轉換爲double或字符串以允許檢查匹配。

下面是這部分的代碼:

正如你所看到的,可以輸入參數值criteria需要轉換回while循環前一個特定的數據類型檢查匹配。我對如何做到這一點略有損失,因爲我不知道C++中的任何鑄造方法在這種情況下會很有用。

我能想到的唯一的事情會是這樣的:

try 
{ 
    //example method 
    convertToDouble(criteria); 
} 
catch (SomeKindOfNumberException ex) 
{ 
    //cannot be a double 
    //so must be string 
    convertToString(criteria); 
} 

任何幫助是極大的讚賞。

謝謝, 馬克

回答

1

怎麼這樣呢?

#include <iostream> 

template<typename T> 
T FuncB(T x) { 
    std::cout << "generic T "; 
    return x; 
} 

template<> 
double FuncB<double>(double x) { 
    std::cout << "double "; 
    return 0.123; 
} 

template<> 
std::string FuncB<std::string>(std::string x) { 
    std::cout << "string "; 
    return "xyz"; 
} 

template <typename T> 
void FuncA(T param) { 
    std::cout << "FuncA: "; 
    T tmp = FuncB(param); 
    std::cout << tmp << std::endl; 
} 

int main() { 
    std::string s = "abc"; 

    FuncA(0.1); 
    FuncA(s); 
    FuncA(1); 
} 

FuncA可以接收任何T,但它使用專用於某些特定類型的FuncB。如果你想保留或刪除FuncB(T)來支持/避免使用未知類型。

前面代碼的輸出如下所示:

FuncA: double 0.123 
FuncA: string xyz 
FuncA: generic T 1 
+0

嗨,謝謝你。使用你的例子,如果我想使用這些函數來返回它們各自的int/double/T值並將它們存儲在一個變量中,我該怎麼去做呢? – marcuthh

+0

@marcuthh:我剛剛包括那 – purpletentacle

+0

這已完美運行。謝謝你的時間! – marcuthh

1

也許你可以添加一個Criterion<T>類保持用戶價值和委託測試到這個類:

template<class T> 
class Criterion { 
    T m_value; 
public: 
    Criterion(T&& value) // allow implicit conversion 
    : m_value(std::forward<T>(value)) {} 
    bool appliesTo(const TransactionList &l); // provide default implementation if any 
} 

template<> 
inline bool Criterion<double>::appliesTo(const TransactionList &l) { 
    /* check against double field */ 
} 

template<> 
inline bool Criterion<std::string>::appliesTo(const TransactionList &l) { 
    /* check against string field */ 
} 

然後你的算法會看像這樣:

template <typename T> 
const TransactionList TransactionList::getTransactionsForSearchCriteria(Criterion<T> criteria) const { 
    TransactionList copy(*this); 
    TransactionList ret; 
    while (copy.size() > 0) 
    { 
     if (criteria.appliesTo(copy)) 
     { 
      //flag as match 
     } 
    } 
} 
0

所以你的T對象是一個公司ntainer,你還沒有給我們提供很多關於它的信息,但是如果你在對象內部使用vector來包含對象,那麼你將會前進。

其次,如果您要使用pair來包含您的vector,您可以利用get來選擇正確的成員。

所以,寫答案的目的,我TransactionList對象將是這樣的:

typedef pair<vector<string>, vector<double>> TransactionList; 

然後我們可以重寫你的函數:

template <typename T> 
TransactionList getTransactionsForSearchCriteria(TransactionList result, T criteria) { 
    auto& attribute = get<vector<T>>(result); 
    auto it = find(attribute.begin(), attribute.end(), criteria); 

    //check that criteria matches transaction attribute 
    if(it != attribute.end()) { 
     //flag as match 
    } 
    //guessing what you want to do with this: attribute.insert(it, criteria); return result; 
} 

如果你能保證名單已維護排序,該標準提供二進制搜索功能,這將顯着提高您的大型收藏的性能:

template <typename T> 
transactionList getTransactionsForSearchCriteria(transactionList result, T criteria) { 
    auto& attribute = get<vector<T>>(result); 
    auto it = lower_bound(attribute.begin(), attribute.end(), criteria); 

    //check that criteria matches transaction attribute 
    if(it != attribute.end() && *it == criteria) { 
     //flag as match 
    } 
    //guessing what you want to do with this: attribute.insert(it, criteria); return result; 
} 

至於確定你的輸入值使用TransactionList result時,採取所有輸入作爲string然後看你是否能成功地消耗整個stringdoublestringdoubleForcing String to int Function to Consume Entire String

size_t size; 
double num; 
string i; 
cin >> i; 

if(sscanf(i.c_str(), "%lf%n", &num, &size) == 1 && size == i.size()) { 
    result = getTransactionsForSearchCriteria(result, num); 
} else { 
    result = getTransaztionsForSearchCriteria(result, i); 
} 

Live Example

相關問題