• 締切済み

dequeにconstが混ざったアイテムの削除

こんにちわ。 関数のパラメータにpairのdequeを渡したときにfirstを変えてほしくないために 以下のようにプログラムを書きました。ただしdequeの中身自体は削除したいのですが、 エラーになってしまいます。 deque< pair< const int, int > > listTest ; pair< int, int > pairTest ; pairTest.first = 0 ; pairTest.second = 4 ; listTest.push_back( pairTest ) ; pairTest.first = 1 ; pairTest.second = 5 ; listTest.push_back( pairTest ) ; pairTest.first = 2 ; pairTest.second = 6 ; listTest.push_back( pairTest ) ; pairTest.first = 3 ; pairTest.second = 7 ; listTest.push_back( pairTest ) ; // ↓ エラー(こちらは自分の期待通り)。 listTest.begin()->first = 10 ; // secondは変更できる(こちらも自分の期待通り)。 listTest.begin()->second = 20 ; // ↓ エラー。 listTest.erase( listTest.begin()) ; 上記のリストでリストのアイテム自体は削除できるようにしたいのですが、うまく行きません。 テンプレート引数にconstが混ざるとリスト自体も削除できなくなってしまうのでしょうか ? もしエラーを解決できる方法をご存じの方がいらっしゃいましたら教えていただけないでしょうか。 よろしくお願いします。

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

そもそも「コンテナに入れるデータは代入可能じゃないとだめ」と規格に書いてありますな. あと, これは大きな突込みどころなんだけど「取り除きたいのは先頭や末尾だけではありませんので」というなら deque を使うべきではない.

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.2

>上記のリストでリストのアイテム自体は削除できるようにしたいのですが、うまく行きません。 erase() は deque の途中の要素を削除する場合に内容をスライドする可能性があるので、 格納されるオブジェクトがコピー可能でなければならないのでしょう。 先頭要素または末尾の要素を取り除くだけなら pop_front() や pop_back() を利用すればよいのではないですか?

Daogouzaka
質問者

お礼

koko_u_ さん、レスありがとうございます。 取り除きたいのは先頭や末尾だけではありませんので、 machongola さんが提示して頂いた方法が私としては回答になります。 これは私が、 > listTest.erase( listTest.begin()) ; と書いたのが koko_u_ さんに余計な誤解をさせてしまったと思います。 大変失礼しました。質問するときは端折らずにちゃんと書くように致します。

回答No.1

 こんばんは。  deque< pair< int, int > >の参照に変換すれば通ります。 typedef deque< pair< const int, int > > const_type; typedef deque< pair< int, int > > unconst_type; //unconst_type::iterator&に変換してから複写 unconst_type::iterator it = (unconst_type::iterator&)(listTest.begin()); // ↓ 消せる。 ((unconst_type&)listTest).erase(it) ; // 確認してみる for(const_type::iterator it2 = listTest.begin(); it2 != listTest.end(); ++it2) printf("%d %d\n", it2->first, it2->second);

Daogouzaka
質問者

お礼

machongola さん、こんにちは。 提示して頂いた方法で期待する動作をしました。 iterator をキャストする発想はありませんでした。 これはこの質問だけではなく、他には応用が効きそうです。 自分の書くプログラムの幅が広がりそうです。 ありがとうございました。

関連するQ&A

  • Pascalへの変換について

    C言語のプログラムをPascalに変更してほしいのですが 分かりません。 #include<iostream> #include<list> #include<utility> #include<algorithm> void output(const std::pair<char,int>&p){ std::cout << "入力文字'"<< p.first << "' 入力回数 "<< p.second << std::endl; } int main(){ typedef std::list<std::pair<char,int> >list_t; list_t count; for(char c;std::cin.get(c) && c != '.';){ if(c == '\n')continue; list_t::iterator it = count.begin(),end=count.end(); for(;it != end;++it) if(it->first == c)break; if(it == end){ count.push_back(std::make_pair(c,0)); it = count.end(); --it; } ++it->second; } std::for_each(count.begin(),count.end(),output); } よろしくお願いします

  • const参照メンバを含む要素のvector

    久しぶりに趣味でプログラミングしてます。 const参照のメンバを含むオブジェクトを要素に持つvector って使えます? 下記はbcc32でコンパイルするとエラーが出ます。 _algobase.h 145:コンパイラは 'operator=' クラスの hoge を作成できない(関数 _STL::hoge * __copy<hoge *,hoge *,int>(hoge *,hoge *,hoge *,const random_access_iterator_tag &,int *) ) ちなみにv.clear();をコメントアウトするとコンパイルは通り実行も問題なくできます。 clear()の替わりにpop_back()としてもコンパイルは通り実行も問題なくできます。 コンパイラーのバグ?そもそもこんなことをしてはダメ? よろしくお願いします。 class hoge { public:  hoge(const int &i):_i(i){};  virtual ~hoge(){};  operator int () const {return _i;}  const int &_i; }; int main() {  int i1=1;  int i2=2;  hoge h1(i1);  hoge h2(i2);  std::vector<hoge > v;  v.push_back(h1);  v.push_back(h2);  v.clear();  std::vector<hoge >::iterator iter = v.begin();  while( iter != v.end() ){   std::cout << *iter << "\n";   ++iter;  }  return 0; }

  • コンテナ要素の削除について

    今vectorの勉強をしているのですが、要素を削除できなくて困っています。 下記のch1とch2において、 vector<int> ch1; vector<int> ch2; ch1.push_back(10); ch1.push_back(11); ch1.push_back(12); ch1.push_back(13); ch1.push_back(14); ch1.push_back(15); ch2.push_back(13); ch2.push_back(14); ch2.push_back(15); ch1とch2が一致する要素は削除して、一致しない値を得たいのですがどうしたらいいのでしょうか? 結果としては、 ch1に、10・11・12のみが残る感じです。 よろしくお願い致します。 int ch1_size = ch1.size(); int ch2_size = ch2.size(); vector<int>:: iterator itr1; itr1=ch2.begin(); for(int a=0;a<ch1_size;a++){ for(int b=0;b<ch2_size;b++){ if(ch1[a]==ch2[b]){ itr1+b; ch1.erase(itr1); } } }

  • VisualC++2005にてerror C2664と出ます。STLのpairで引数を変換できないとのことです

    私は現在、VisualC++2005 Express Editionにてプログラミングを行っているのですが、次のようなエラーが出てしまいます。 c:\program files\microsoft visual studio 8\vc\include\utility(44) : error C2664: 'std::pair<_Ty1,_Ty2>::pair(const std::pair<_Ty1,_Ty2> &)' : 1 番目の引数を 'const double' から 'const std::pair<_Ty1,_Ty2> &' に変換できません。(新しい機能 ; ヘルプを参照) with [ _Ty1=double, _Ty2=double ] 理由: 'const double' から 'const std::pair<_Ty1,_Ty2>' へは変換できません。 with [ _Ty1=double, _Ty2=double ] コンストラクタはソース型を持てません、またはコンストラクタのオーバーロードの解決があいまいです。 コードは次のものです。 typedef std::pair<double, double> doublesPair; typedef std::pair<doublesPair, double> posValDouble; typedef std::list<posValDouble> posValDoubleList; ---------------------------------------------------- posValDoubleList::iterator pvdl_ite = pvdl.begin(); Double ax = pvdl_ite->first.first; ay = pvdl_ite->first.second; az = pvdl_ite->second; pvdl_ite++; bx = --- - - - 解決策を教えていただけたらと思います。 よろしくお願いします。

  • std::lower_boundについて

    こんにちは。 std::vector< int* > IntArray; IntArray.push_back( new int( 0 ) ); IntArray.push_back( new int( 2 ) ); IntArray.push_back( new int( 1 ) ); IntArray.push_back( new int( 6 ) ); IntArray.push_back( new int( 5 ) ); IntArray.push_back( new int( 7 ) ); というint型のポインタが格納されているIntArrayを bool cmp( const int* lhs, const int* rhs ) {   return *lhs < *rhs; } std::sort( IntArray.begin(), IntArray.end(), cmp ); として並べ替えたとします。 そこで新しく new int( 4 )をソートされた順番を壊さない位置に挿入したいと思いlower_boundを使用しようと思いました。 しかし、lower_boundの使い方がいまいちわかりません。 int *p = new int( 4 ); bool cmp2( const int* lhs, const int* rhs ) {   return *lhs < *rhs; } std::lower_bound(  IntArray.begin(),  IntArray.end(),  p,  cmp2 ); 上記のように使用すればこの場合だと変数pを挿入する位置が返ってくるのでしょうか? 間違えているとしたら、どのように修正すれば変数pを挿入できる位置が返ってくるように書き直すことができるでしょうか?(むしろそういった実装は可能なのでしょうか) よろしくお願いします。 今回は特殊ケースでの問題ですのでint* pをintに修正する、挿入してから再度ソートする、といったことはなしでお願いします。あくまでもlower_boundで実装する場合のコードについてでよろしくお願いします。 /*   VisualStudio 2008 academic edition   Window7 64bit */

  • C++ iteator const を使ったプログラムがコンパイルできない

    以下のプログラムがコンパイルできません。 理由もよく分かりません。 ----------------- #include <algorithm> #include <list> struct Hoge { std::list<Hoge*> l; Hoge * f() const { std::list<Hoge*>::iterator i = l.begin(); return 0; } }; -------------------- g++ 4.1.1 を使っていますが % g++ -c test1.cc test1.cc: In member function 'Hoge* Hoge::f() const': test1.cc:8: error: conversion from 'std::_List_const_iterator<Hoge*>' to non-scalar type 'std::_List_iterator<Hoge*>' requested となります。 l.begin() が const で代入できないということだと思うのですが std::list<Hoge*> l; の部分には const を使っていませんし良く分かりません。 また、 Hoge * eval() const { の const を消すか、 std::list<Hoge*>::iterator i = l.begin(); の代入をやめると コンパイルが通ります。 const は return するポインタの先の領域を変更不可にしている と解釈しているのですが、戻り値と関係ない代入がどうして影響を受けるのかが謎です。 (実際は、もう少し違う大きいプログラムですが関係なさそうな部分を削って 上でも同様のエラーメッセージが出ることを確認しました。)

  • マップとアルゴリズム

    またまた質問です。 以下の処理をさせるとエラーが出ます。 どなたか見ていただけますか? 環境はWindows XP, Visual Studio.NETです。 -----処理部分------------------ map<char, int> m; for(i=0; i<10; i++){  m.insert(pair<char, int>('A'+i, i)); } reverse(m.begin(), m.end()); map<char, int>::iterator p; p = m.begin(); while( p != m.end() ){  cout << p->first << " " << p->second << endl;  p++; } ------以下エラーログ--------------- C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(16) : error C2166: 左辺値は const オブジェクトに指定されています。 C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(46) : コンパイルされたクラスのテンプレートのインスタンス化 'void std::swap<const _Ty1>(const _Ty &,const _Ty &)' の参照を確認してください with [ _Ty1=int, _Ty=int ] C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(45): クラス テンプレートのメンバ関数 'void std::pair<_Ty1,_Ty2>::swap(std::pair<_Ty1,_Ty2>::_Myt &)' のコンパイル中 with [ _Ty1=const int, _Ty2=int ] ClusteringMain.cpp(45) : コンパイルされたクラスのテンプレートのインスタンス化 'std::pair<_Ty1,_Ty2>' の参照を確認してください with [ _Ty1=const int, _Ty2=int ] C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(16) : error C2166: 左辺値は const オブジェクトに指定されています。

  • デフォルトコンストラクタで分からないことがあります。

    デフォルトコンストラクタ デフォルトコンストラクタで分からないことがあります。 以下のコードです。 > template<class T1, class T2> > struct pair > { > T1 first; // 1つ目の値 > T2 second; // 2つ目の値 > > // デフォルトコンストラクタ > pair() : first( T1() ), second( T2() ){} > > // 引数付きコンストラクタ > pair(const T1& a, const T2& b) : first( a ), second( b ){} > }; このコードの中の pair() : first( T1() ), second( T2() ){} で初期化子による初期化をしていると思うのですが「T1()」と「T2()」は具体的に 何をしているのでしょうか?自分の想像ではfirstとsecondに何か初期化の値を代入して初期化していると思うのですが何でしょうか? なお、その次のコードの意味は分かります。 > pair(const T1& a, const T2& b) : first( a ), second( b ){} これは、引数a,bを持っていてそれぞれfirstにaを代入してsecondにbを代入して初期化しているのですよね。 なお、このコードが掲載されているサイトはここです。 http://www.geocities.jp/ky_webid/cpp/library/011.html

  • VC2013のSTLでlength_error

     VC2010で作っていたあるプロジェクトがあるのですが、それをVC2013に移植しました。そのプロジェクトではstd::dequeを使っているのですが、deque::push_backするときにstd::length_errorという例外を投げるようになってしまいました。サイズが0のコンテナにpush_backした時点で例外が投げられます。  deque<T>のTには、そこそこメンバ変数が多めのクラスが指定され、push_backされる前にビットマップ用の領域がクラスのインスタンスで確保されてからpush_backされます。  コンテナのデフォルトアロケーターが確保するサイズに比べてクラスのサイズが合わないのかなと検討をつけているところなのですが、よくわかっておりません。  心当たりのある方にご教授いただければ幸いです。

  • CStringを含むconst構造体

    VC++6.0で typedef struct { int i; CString s; } StructTest; という構造体を作ったとして const StructTest m_STest = { 1, "TEST" }; とすると 『error C2552: 'm_STest' : 初期化子リストによる個別の識別子の初期化に誤りがあります。』 と出ます。 このような記述は出来ないのでしょうか?

専門家に質問してみよう