C ++ - 将模板类型对象转换为特定数据类型

时间:2016-04-15 10:46:08

标签: c++ templates casting

我正在使用模板函数searchByCriteria<T>,我希望能够使用stringdouble运行该函数。我有一个具有stringdouble属性的自定义对象列表,我希望能够使用此函数来检查条件值(用户输入的任何类型) ,检查相同类型的对象属性中的匹配。

即。用户输入double值,检查对象集合是否匹配double值。用户输入字符串值,检查对象集合是否匹配字符串值。

我遇到的问题是输入值后,会将其传递给另一个模板函数,以便根据列表中的元素进行检查。此时,作为参数传递的T对象需要转换为double或字符串以允许检查匹配。

以下是此部分的代码:

//get a sub-list of transactions
//of all that match specified search criteria
template <typename T>
const TransactionList TransactionList::getTransactionsForSearchCriteria(T criteria) const {
    //make a copy of list to avoid deleting existing data
    TransactionList copy(*this);
    //to have appropriate transactions added in
    //then returned as copy
    TransactionList ret;

    //////////////////////////////////////////
    //before checking for matches can start///
    //must ID datatype of T instance//////////
    //////////////////////////////////////////

    //check all transactions until list empty
    while (copy.size() > 0)
    {
        //check that criteria matches transaction attribute
        if (/*converted criteria matches corresponding attribute*/)
        {
            //flag as match
        }
    }
}

如您所见,在输入while循环以检查匹配之前,需要将参数值criteria转换回特定的数据类型。我对如何做到这一点略有不足,因为我不知道在这种情况下C ++中的任何转换方法都会有用。

我唯一能想到的就是:

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

非常感谢任何帮助。

谢谢, 标记

3 个答案:

答案 0 :(得分:1)

How about something like this?

#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 can receive any T but it uses FuncB which is specialized for some specific types. If you want you can keep or delete FuncB(T) to support/avoid using unknown types.

The output of the previous code looks like:

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

答案 1 :(得分: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
        }
    }
}

答案 2 :(得分:0)

因此,您的T对象是一个容器,但您还没有向我们提供大量信息,但是如果您在对象内部使用vector来包含对象,那么#39;将走在前面。

其次,如果您使用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;
}

至于在使用string时确定您输入的值是double还是TransactionList result,请将所有输入作为string,然后查看您是否可以使用整个string已成功转换为doubleForcing 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