2016-09-26 7 views
1

入れ子のベクトルをすべての次元でサイズ変更するテンプレート関数を作成しようとしています。テンプレート内の再帰的な入れ子ベクトルのサイズを変更する

かなりこのように: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のインデックスを維持するために第4の入力が必要でしょうか?

Btw。、私は目的の最初の薄暗度をスキップしています、それはすでに正しいサイズです。

助けてください。

+0

ベクトルの "すべてのディメンション"とは何ですか? – Hayt

+0

Hayt:入れ子になったベクトルごとに1次元。したがって、ベクター、1つの薄暗く、ベクター> 2つの薄暗い等。 – Wiebe

+0

@ウィーベーあなたは別の答えとしてコードを投稿することができます(私はSOの質問の中に回答を投稿するのは良い方法だとは思わない) –

答えて

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 
} 
+0

ありがとうございます。私のコードでいくつかの詳細を修正するのに役立ちました。 – Wiebe

+0

あなたの提案したコードは、私が投稿した作業のソリューションより効率的(またはそれ以外の点でより良い)ですか? – Wiebe

+0

@ウィーベットそれを聞いてうれしい:) –

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

実際の問題は、テンプレートの各インスタンスが、多次元ベクトルの最後の次元とベクトルの他のすべての次元という2つの可能性のコードを生成する必要があることです。後者の場合、ベクトルの次の次元を再帰する必要があり、前者の場合には明らかなコンパイルエラーが発生します。ベクトルの次元数と一致している必要があり、各次元のサイズを与え、

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

サイジングベクター:

これは、特殊化を必要とします。余分なサイズは無視されます。サイズが小さくなると、先頭のサイズがリサイズされるだけです。

+0

ありがとう。私は、現在どのソリューションを使用するのか、各ソリューションの過去を把握しなければなりません。そして、あなたは間違いの余地があるので、ある時点では、nrを埋め込むクラスを作るほうがよいでしょう。dims、dimのサイズと入れ子のベクトル、の... – Wiebe

関連する問題