在模板

时间:2016-09-26 10:18:23

标签: c++ templates vector

我试图制作一个模板函数来调整嵌套向量的所有维度。

非常像这样:resizing multidimensional vector,但对于任意的nr。昏暗的。

(我想)该函数将(至少)接受对向量(或vector<vector<T>>v<v<v<T>>>等)的引用以及具有所需大小的向量。我现在也在尺寸矢量中有索引,但可能不需要它。

到目前为止,这是我最终得到的结果(可能是完全错误的):

template<typename V> void resize(vector<V> & V1, vector<int32_t> t, int32_t index) {
    int32_t current_size=t.at(index); 
    cout << "resize dim [" << index << "] to size " << current_size <<endl ;
    ++index;
    if (index < t.size()) {
        // for each element ??
        // for( int i = 0 ; i < V1.size(); i++ ) { resize (V1.at(i), t, index); } // doesn't work
        // for( auto const& e : V1 ) { resize (e, t, index); } // doesn't work
         // resize( V1, t, index); // recursive call, works, but doesn't do anything
    }

我想避免复制V1或其任何内容。我不确定是否有一种方法可以使用迭代器或传递引用的循环。如果没有,可能需要进行第四次输入以保持V1的索引?

顺便说一句,我是故意跳过第一个昏暗的,它已经是正确的尺寸。

任何帮助表示感谢。

3 个答案:

答案 0 :(得分:1)

你可能正在寻找类似这样的东西(这是符合c ++ 14标准的解决方案,类似的对于c ++ 11来说会有点棘手,但仍然可能):

#include <vector>
#include <tuple>
#include <utility>

template <class NestedVectorElement, class Tuple>
void nested_resize(std::vector<std::vector<NestedVectorElement>> &v, Tuple &&t);

template <class VectorElement, class Tuple>
void nested_resize(std::vector<VectorElement> &v, Tuple &&t);

template <class Vector, class Tuple, size_t... Is>
void nested_resize_impl(Vector &v, Tuple &&t, std::index_sequence<Is...>) {
   v.resize(std::get<0>(t));
   for(auto &nv: v) {
      nested_resize(nv, std::forward_as_tuple(std::get<Is + 1>(t)...));
   }
}

template <class NestedVectorElement, class Tuple>
void nested_resize(std::vector<std::vector<NestedVectorElement>> &v, Tuple &&t) {
   nested_resize_impl(v, t, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>{});
}

template <class VectorElement, class Tuple>
void nested_resize(std::vector<VectorElement> &v, Tuple &&t) {
   v.resize(std::get<0>(t));
}

int main() {
   std::vector<std::vector<std::vector<int>>> matrix;
   nested_resize(matrix, std::make_tuple(3, 2, 3));
   matrix.at(2).at(1).at(2) = 0; // at gives you an access only if element exists else throws an exception
}

答案 1 :(得分:1)

这有效:

    template<typename V> void resizer(V & V1, vector<int32_t> const & t, int32_t index) {}

    template<typename V> void resizer(vector<V> & V1, vector<int32_t> const & t, int32_t index) {
        int32_t current_size=t.at(index); 
        V1.resize(t.at(index) );
        ++index;
        if (index < t.size() ) {
            for( auto & e : V1 )  {
                resizer (e , t, index);
            }
        }
    }

但这实际上要好一点,因为我们并不是在不必要地迭代最后一个维度的元素:

    template<typename V> void resizer(vector<V> & V1, vector<int32_t> const & t, int32_t index) {
        int32_t current_size=t.at(index); 
        V1.resize(t.at(index) );
    }

    template<typename V> void resizer(vector<std::vector<V>> & V1, vector<int32_t> const & t, int32_t index) {
        int32_t current_size=t.at(index); 
        V1.resize(t.at(index) );
        ++index;
        if (index < t.size() ) {
            for( auto & e : V1 )  {
                resizer (e , t, index);
            }
        }
    }

答案 2 :(得分:1)

这里真正的问题是模板的每个实例都需要为两种可能性生成代码:多维向量的最后一个维度,以及向量的所有其他维度。在后者的情况下,有必要对向量的以下维度进行递归,这将导致在前者的情况下出现明显的编译错误。

这需要专业化:

#include <vector>
#include <iostream>

template<typename V, typename iter_type>
class resize_dim {

public:
    static void resize(V & V1,
               iter_type b, iter_type e)
    {
        if (b == e)
            return;

        V1.resize(*b);
    }
};

template<typename V, typename iter_type>
class resize_dim<std::vector<std::vector<V>>, iter_type> {

 public:

    static void resize(std::vector<std::vector<V>> & V1,
               iter_type b, iter_type e)
    {
        if (b == e)
            return;

        V1.resize(*b);

        ++b;

        for (typename std::vector<std::vector<V>>::iterator
                 vb=V1.begin(),
                 ve=V1.end(); vb != ve; ++vb)
            resize_dim<std::vector<V>, iter_type>::resize(*vb, b, e);
    }
};

template<typename V>
void resize(V &v, const std::vector<size_t> &dimensions)
{

    resize_dim<V, std::vector<size_t>::const_iterator>
        ::resize(v, dimensions.begin(), dimensions.end());
}

int main()
{
    std::vector<std::vector<std::vector<int>>> v;

    std::vector<size_t> d;

    d.push_back(3);
    d.push_back(3);
    d.push_back(3);

    resize(v, d);

    std::cout << "Ok" << std::endl;
    return 0;
}

大小调整向量,给出每个维度的大小应该与向量中的维度数量相匹配。额外的尺寸被忽略。较小的尺寸只会导致尺寸调整的尺寸。