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;
}