我必须过滤一个容器,并且每个项目的副本都很昂贵。所以我想出了这个C ++代码..也许我想念一个更好的概念。请给出意见。同样重要的是计数和清空等操作也要快。
下面的示例将创建一个包含某些项目的向量,并返回过滤后的副本并执行一些布尔运算。
#include <vector>
#include <functional>
template <class X> struct filterChainT {
/// the list here
const X & list;
/// take store type from access operator
typedef decltype(list[0]) storeType;
/// the test functions
std::function<bool(storeType &) > tests[10];
/// counting the test (don´t use array here)
size_t countTest;
/// ctor with given list
filterChainT(const X & list):list(list),countTest(0) { }
/// add a rule here
filterChainT<X> & apply(const std::function<bool(storeType &) > & fnc)
{
tests[countTest++] = fnc;
return *this;
}
/// downcast to container (will return the filter copy)
operator X() const
{
X ret;
eval([&](const storeType & hit) { ret.push_back(hit); return false; });
return ret;
}
/// just count item after filter
int count() const
{
int count = 0;
eval([&](const storeType hit) { count++; return false; });
return count;
}
bool operator==(int number) const { return count() == number; }
bool operator>(int number) const
{
int count = 0;
return eval([&](const storeType & hit) { return ++count>number; });
}
bool operator<(int number) const
{
int count = 0;
return !eval([&](const storeType & hit) { return ++count>=number; });
}
//// the magic eval functions. Return true if the fnc object abort the loop
template <class FNC> bool eval(const FNC fnc) const
{
for (auto i : list)
{
for (size_t t = 0; t < countTest; t++)
{
if (!tests[t](i))
goto next;
}
if (fnc(i))
return true;
next:;
}
return false;
}
};
struct myFilter : public filterChainT < std::vector<int>> {
myFilter(const std::vector<int> & in) :filterChainT<std::vector<int>>(in){ };
// filter items i%2==0
myFilter & mod()
{
apply([](const int & i) { return i % 2; });
return *this;
}
// filter items smaller than x
myFilter & smaller(int x)
{
apply([=](const int & i) { return i<x; });
return *this;
}
};
int main()
{
std::vector<int> vec;
vec.push_back(1);
vec.push_back(3);
vec.push_back(10);
// apply filter and return result use two filters „mod“ and „smaller“
std::vector<int> ret = myFilter(vec).mod().smaller(5);
// just see if they are less then 2 items in list same filter than above
bool res1 = myFilter(vec).mod().smaller(5) < 2;
// some custom without the helper -> filter all items larger than 3 and put in list
std::vector<int> result=filterChainT < std::vector<int>>(vec).apply([](const int & p) { return p > 3; });
}
致谢 马库斯
答案 0 :(得分:0)
带有“表达式模板”的提示效果很好。比我的帖子快两倍。现在,代码如下所示。非常感谢您指出正确的地方。
我使用了与WIKI条目相同的概念,添加了加号操作以创建过滤器链,并添加了最终函数以使用该过滤器减少给定列表。
template <class T> struct filterNodeBaseT {
template <class X> bool apply(const X& x) const { return static_cast<T const & >(*this).apply(x); }
template <class LST> LST filter(const LST & input) const
{ LST ret;
for (auto i : input)
{ if (this->apply(i))
ret.push_back(i);
}
return ret;
}
template <class LST> int count(const LST & input) const
{ int ret = 0;
for (auto i : input)
{ if (this->apply(i))
ret++;
}
return ret;
}
};
template <class T1, class T2> struct filterCombine : public filterNodeBaseT<filterCombine<T1, T2> > {
const T1 & t1;
const T2 & t2;
filterCombine(const T1 & t1, const T2 & t2) :t1(t1), t2(t2) { }
template <class X> bool apply(const X & x) const { return t1.apply(x) && t2.apply(x); }
};
template <class T1,class T2> filterCombine<T1,T2> operator + (const T1 & t1,const T2 & t2)
{ return filterCombine<T1,T2>(t1,t2); }
struct filterNodeSmaller : public filterNodeBaseT<filterNodeSmaller> {
int limit;
filterNodeSmaller(int limit) :limit(limit) {};
bool apply(const int & x) const { return x < limit; }
};
struct filterNodeLarger: public filterNodeBaseT<filterNodeLarger> {
int limit;
filterNodeLarger(int limit) :limit(limit) {};
bool apply(const int & x) const { return x > limit; }
};
struct filterNodeMod : public filterNodeBaseT<filterNodeMod> {
bool apply(const int & x) const { return x % 2; }
};
struct filterStrlenLarger : public filterNodeBaseT<filterStrlenLarger> {
int limit;
filterStrlenLarger(int limit) :limit(limit) { };
bool apply(const std::string & s) const { return s.length() > limit; }
};
struct filterStrGreater : public filterNodeBaseT<filterStrGreater> {
std::string cmp;
filterStrGreater(const std::string & cmp) :cmp(cmp) { };
bool apply(const std::string & s) const { return s>cmp; }
};
_declspec(noinline) void nodeTest()
{
std::vector<int> intList;
intList.push_back(1); intList.push_back(3); intList.push_back(4);
int count= (filterNodeMod() + filterNodeSmaller(5)+ filterNodeLarger(1)).count(intList);
std::vector<int> resList1= (filterNodeMod() + filterNodeSmaller(5)+filterNodeLarger(1)).filter(intList);
printf("%d\n", count);
std::vector<std::string> strList;
strList.push_back("Hello");
strList.push_back("World");
strList.push_back("!");
count = (filterStrlenLarger(3)+filterStrGreater("Hello")).count(strList);
std::vector<std::string> resList2= (filterStrlenLarger(3) + filterStrGreater("Hello")).filter(strList);
printf("%d\n", count);
}