C++ 如何计算向量递归类型中的非空向量
我有一个类型可以定义为向量的向量的向量的向量。。。指整型向量。例如:C++ 如何计算向量递归类型中的非空向量,c++,stl,c++98,C++,Stl,C++98,我有一个类型可以定义为向量的向量的向量的向量。。。指整型向量。例如: std::vector<std::vector<std::vector<std::vector< std::vector<signed char> > > > > _data; 但是,我如何创建一个模板(支持向量、列表或共享相同API的任何类型的容器)函数来为任何深度(超过4级)创建模板呢?我认为递归是正确的方法,但不知道如何使用模板 欢迎提供所有帮助和建议,因为我
std::vector<std::vector<std::vector<std::vector< std::vector<signed char> > > > > _data;
但是,我如何创建一个模板(支持向量、列表或共享相同API的任何类型的容器)函数来为任何深度(超过4级)创建模板呢?我认为递归是正确的方法,但不知道如何使用模板
欢迎提供所有帮助和建议,因为我非常确定有不止一种解决方案。可能是类似的吗?(它使用
std::enable_if
所以这是一个C++11答案,但也许您可以使用boost答案)
模板
typename std::enable_if::type
非空(常量U&r)
{
return!r.empty();
}
模板
typename std::enable_if::value,std::size\u t>::type
非空(常量U&r)
{
标准:尺寸=0;
用于(自动和it:r)
{
res+=非_清空(it);
}
返回res;
}
用法:
auto non_empty_terminal = non_empties<signed char>(_data);
自动非空终端=非空(\u数据);
您必须将“stop”类型作为模板参数,因此它可能并不理想
活动示例您可以进行模式匹配以计算深度
template <typename Base>
struct NestedVectors //non vector match
{
static const size_t depth=0;
static size_t count_empty(const Base& b)
{
throw std::string("cant be here");
}
};
template <class Rv>
struct NestedVectors<std::vector<Rv> >
{
static const size_t depth=1 + NestedVectors<Rv>::depth ;
static size_t count_empty(const std::vector<Rv>& vec)
{
size_t r=0;
if(NestedVectors<Rv>::depth == 0)
{
if(vec.empty())
return 1;
}
else
{
for(size_t i =0; i < vec.size() ; ++i)
{
r+=NestedVectors<Rv>::count_empty(vec[i]);
}
}
return r;
}
};
int main()
{
typedef std::vector<
std::vector<
std::vector<
std::vector<
std::vector<
signed char
> > > > > data_t;
data_t t;
std::cout << NestedVectors<data_t>::depth << " " << NestedVectors<data_t>::count_empty(t);
}
模板
结构嵌套向量//非向量匹配
{
静态常量大小\u t深度=0;
静态大小\u t计数\u为空(常数基数和b)
{
抛出std::string(“不能在这里”);
}
};
模板
结构嵌套向量
{
静态常量大小\u t深度=1+嵌套向量::深度;
静态大小\u t计数\u为空(const std::vector和vec)
{
尺寸r=0;
if(NestedVectors::depth==0)
{
if(vec.empty())
返回1;
}
其他的
{
对于(大小i=0;i>>>>数据;
数据;
std::cout这是一个C++98解决方案,它只使用基本的模板专门化:
template<typename T> struct VectorCounter {
/* no count method: this is an error */
};
template<typename U> struct VectorCounter<vector<U> > {
static int count(const vector<U> &v) {
return (int)v.empty();
}
};
template<typename V> struct VectorCounter<vector<vector<V> > > {
static int count(const vector<vector<V> > &v) {
int ret = 0;
for(typename vector<vector<V> >::const_iterator it=v.cbegin(); it!=v.cend(); ++it) {
ret += VectorCounter<vector<V> >::count(*it);
}
return ret;
}
};
template<typename T> int count_nonempty_vectors(const T &v) {
return VectorCounter<T>::count(v);
}
两者都打印出“60”.是否允许使用C++11作为解决方案?不,这只是问题的一部分,仅限C++98!感谢这是一个非常好的代码,我想我需要多次阅读它才能完全理解它的工作原理,但据我所知,它应该适用于任何存在空api的容器,所以请使用deque列表等,那么为什么你说它只适用于vector?是的,应该如此使用value\u type字段处理每个continer,但是std::map的value\u type是一对,因此您必须将T=std::pair放入,这不是很简单。@alexbuisson是的,可以与其他STL容器类型一起使用,例如std::set
和std::deque
,在Live example链接中添加了测试。嗨,不要检查y我们的答案,即使它是一种完全有效的方法a,d在一开始我认为使用boost/utilities,我可以使用C++98编译器将C++11代码移植到老年,但我失败了……但这项出色的工作非常出色,它展示了C++11的强大功能!即使代码非常好,问题是计算非空代码的数量容器在最深处,但是thanks@alexbuisson这应该行得通,我没有做过很多测试,只是编译器我使用了这个解决方案,主要是因为它适用于C++98,即使我必须将“empty()”切换到“!empty()”:)
template <typename Base>
struct NestedVectors //non vector match
{
static const size_t depth=0;
static size_t count_empty(const Base& b)
{
throw std::string("cant be here");
}
};
template <class Rv>
struct NestedVectors<std::vector<Rv> >
{
static const size_t depth=1 + NestedVectors<Rv>::depth ;
static size_t count_empty(const std::vector<Rv>& vec)
{
size_t r=0;
if(NestedVectors<Rv>::depth == 0)
{
if(vec.empty())
return 1;
}
else
{
for(size_t i =0; i < vec.size() ; ++i)
{
r+=NestedVectors<Rv>::count_empty(vec[i]);
}
}
return r;
}
};
int main()
{
typedef std::vector<
std::vector<
std::vector<
std::vector<
std::vector<
signed char
> > > > > data_t;
data_t t;
std::cout << NestedVectors<data_t>::depth << " " << NestedVectors<data_t>::count_empty(t);
}
template<typename T> struct VectorCounter {
/* no count method: this is an error */
};
template<typename U> struct VectorCounter<vector<U> > {
static int count(const vector<U> &v) {
return (int)v.empty();
}
};
template<typename V> struct VectorCounter<vector<vector<V> > > {
static int count(const vector<vector<V> > &v) {
int ret = 0;
for(typename vector<vector<V> >::const_iterator it=v.cbegin(); it!=v.cend(); ++it) {
ret += VectorCounter<vector<V> >::count(*it);
}
return ret;
}
};
template<typename T> int count_nonempty_vectors(const T &v) {
return VectorCounter<T>::count(v);
}
#include <iostream>
#include <vector>
using std::vector;
typedef vector<vector<vector<vector<vector<signed char> > > > > data_t;
int count_fixed(const data_t &data) {
int nonEmpty = 0;
for (auto it0 = data.cbegin() ; it0 != data.cend() ; ++it0)
for (auto it1 = it0->cbegin() ; it1 != it0->cend() ; ++it1)
for (auto it2 = it1->cbegin() ; it2 != it1->cend() ; ++it2)
for (auto it3 = it2->cbegin() ; it3 != it2->cend() ; ++it3)
nonEmpty += (unsigned int)(it3->empty());
return nonEmpty;
}
data_t build_data() {
data_t data(5);
int sz = 0;
for (auto it0 = data.begin() ; it0 != data.end() ; ++it0) {
it0->resize(4);
for (auto it1 = it0->begin() ; it1 != it0->end() ; ++it1) {
it1->resize(3);
for (auto it2 = it1->begin() ; it2 != it1->end() ; ++it2) {
it2->resize(2);
it2->at(0).resize(1);
it2->at(1).resize(0);
}
}
}
return data;
};
int main() {
std::cout << count_fixed(build_data()) << std::endl;
std::cout << count_nonempty_vectors(build_data()) << std::endl;
return 0;
}