我正在使用模板函数searchByCriteria<T>
,我希望能够使用string
和double
运行该函数。我有一个具有string
和double
属性的自定义对象列表,我希望能够使用此函数来检查条件值(用户输入的任何类型) ,检查相同类型的对象属性中的匹配。
即。用户输入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);
}
非常感谢任何帮助。
谢谢, 标记
答案 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
已成功转换为double
:Forcing 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);
}