假设我有两个B和D班。 我可以有几种类型的B和D指针容器。例如
std::vector<B *> VecPB;
std::list<D *> ListPD;
假设B和D在某种程度上是相关的,因为它们有一些共同的memmber函数(to_str,is_valid,is_ok,...等)
假设有一个成员函数to_str,可以在B或D的每个元素中调用它来获取字符串 代表B或D. 还有另一个成员函数可以应用于B或D is_valid()。 所以我可以说例如VecPB.front() - &gt; is_valid()
我想要的是能够编写打印B或D类型容器中所有有效元素的函数。
例如,我可以写:
void display_ValidB(const std::vector<B *> & v) {
for(std::vector<B *>::const_iterator it = v.begin(); it != v.end(); ++it)
{
if((*it)->is_valid())
std::cout << (*it)->to_str() << std::endl;
}
}
我可以再抽象一个级别并使用
template<typename T>
void display_valid<const std::vector<T *> & v) {
for(std::vector<T *>::const_iterator it = v.begin(); it != v.end(); ++it)
{
if((*it)->is_valid())
std::cout << (*it)->to_str() << std::endl;
}
}
但现在我的问题是: 有没有办法让我不必为每种类型的容器编写模板函数? 我不想为vector,set,list等编写不同的模板函数....
如何概括这一点,以便display_function可以将lambda函数作为参数,这样我就可以编写
display_function<D>(ListPD, [](const D & d) {return !d->is_ok();});
或类似
display_function<D>(listpd.begin(), listpd.end(), [](const d & d) {return !d->is_ok();});
我最多可以使用C ++ 11但不能使用C ++ 14。
答案 0 :(得分:1)
您可以为容器使用模板参数TContainer
,为通用谓词使用模板参数TF
。
template<typename TContainer, typename TF>
void display_function(const TContainer& v, TF f)
{
for(auto it = v.begin(); it != v.end(); ++it)
{
if(f(*it))
{
std::cout << (*it)->to_str() << std::endl;
}
}
}
display_function(std::vector<D>{/*...*/}, [](const D& d){ return d.is_valid(); });
display_function(std::list<B>{/*...*/}, [](const B& b){ return b.is_ok(); });
您可以传递一个为bool
谓词参数返回TF f
的一元lambda,以及支持.begin()
和.end()
调用的任何类作为const TContainer& v
参数
答案 1 :(得分:1)
template<typename C>
void display_valid(const C& v) {
for(auto& item: v)
if(item->is_valid())
std::cout << item->to_str() << std::endl;
}
如果您希望可以使用std::enable_if这样的类型特征限制模板参数的范围,但只有在您必须以不同方式为不同类型的参数重载函数时才需要这样做。
如果类B
,D
等具有不同的验证方法,那么您可以为验证谓词添加第二个模板参数,如@VittorioRomeo建议并提供lambda或重载函数或函数像这样:
struct Validator {
static
bool operator()(const B& b) {
return b.is_valid();
}
static
bool operator()(const D& d) {
return d.is_ok();
}
};
根据代码的其余部分,基于lambda或functor的解决方案可能有其优缺点(例如,仿函数可以成为默认模板参数,并自动为所有&#34;已知&#34提供必要的验证;班级)。
BTW将原始指针存储在容器中需要额外注意对象生存期和内存管理。您可以考虑使用带容器的智能指针。