スレ殺陣乙彼
前すれ忘れてた(死
(・∀・)ノスレさんお疲れ〜
8 :
デフォルトの名無しさん:02/07/16 16:58
漏れもどっちかというと、からあげよりテンプレートかな。
STLの基本的な勉強を一通り終えた者ですが、Modern C++ Designを読んでも
サパーリちんぷんかんぷんです。
次にどんな本を読めばよいでしょうか。ご指導宜しくお願いします。
modern c++ design1章と2章を読み終わりました。
よく考えたなぁって言う分には今のところ楽しめてるんだけど、
こんなの自分じゃ書けないよ。
こんな俺は、まだ勉強したことのないSTLについて勉強した方が、
実用的だと思うんだけど・・・。
どうしたらいい?
>>11 10です。レスありがとうございます。これから持っている乏しい知識で
どんどん書いてみることにします。
>>12 僕と同じ状態ですね。Effective STLを読破されるとかなり知識がつき
ますよ。
STLといいLokiといいBoostといい よく作った人は天才ばっかりだね〜
15 :
デフォルトの名無しさん:02/07/16 23:16
STLを使い始めると、何でもファンクタにしたくなる罠。
16 :
デフォルトの名無しさん:02/07/17 00:45
ここで質問しても宜しいですか?
class T{ int a; char b; } で、
list<T>をsortする時、 bool operator <() を使って、int aで並べ替えられたけど、
char bでも並び替えたい時はどうすれば良いんでしょう。
bool operator <() を2つ定義するわけにも行かないし。
>>16 比較用のファンクタ作ってわたせばいいじゃん
>>17 binary_functionをpublic継承すればいいのですか?
>>18 継承してもしなくても、どっちでも可能なんじゃない?
>>19 うーん、その継承しない方法がよくわからないのです。普通に書くとファンクタ
でなくて関数になってしまいそうで。
class CompareByChar {
public:
bool operator()(const T& lhs, const T& rhs) const { return lhs.b < rhs.b; }
};
とかじゃだめなの?↑試してないけど。
>>21 なるほど。サンクス。メンバがさらに増えた時の対処も考えてみます。
std::list::sort()には引数にgreater<T>を受け取るバージョンがある。
24 :
前スレ957:02/07/17 06:46
もっかいおねがいします。
mem_fun_ref を使うとインライン展開されないので困った
という場合、自分でループをまわしたらいいんでしょうか?
>>24 自分でループ回せって
それがいやなら、mem_fun_refの変わりをする関数アダプタを作る。
>>26 やっぱり自分でまわすですか。
じゃぁいまの状態で落ち着かせとくことにします。ありがとん。
ところで、 mem_fun_ref_t の替わりを試しに作ってみました。
template< typename T , typename R , R (T::*MEMFUN)() const >
struct static_const_mem_fun_ref_t : std::unary_function< const T& , R >
{
R operator () ( const T& x )
{
return (x.*MEMFUN)();
}
};
unsigned count_empty( const std::vector<std::string>& v )
{
return std::count_if( v.begin() , v.end()
, static_const_mem_fun_ref_t<std::string,bool,&std::string::empty>() );
}
コードは期待通りですが、ソースがあんまりイクナイです。
&std::string::empty を渡すだけで↑みたなのができたらいいなぁ。
う、
>>27のやつ、よく見たら要らなさそうな謎のコードが出てる。
なので「コードは期待通り」ってのを撤回です。
そんなわけでやっぱり素直にループまわした方がいいみたいです。
unsigned count_empty( const std::vector<std::string>& v )
{
unsigned c = 0;
std::vector<std::string>::const_iterator const end = v.end();
for( std::vector<std::string>::const_iterator cur = v.begin() ; cur != end ; ++cur )
if( cur->empty() )
++c;
return c;
}
>>28 ところで、boost::mem_fnもダメなの?
>>29 boost::mem_fn もインライン展開に関しては std::mem_fun[_ref] といっしょみたいです。
VC7 で boost::lexical_cast を include すると bad_cast が定義されてないというエラーがでるんですが、
これを回避する方法はありますでしょうか。
g++ だと大丈夫なんですが。
33 :
デフォルトの名無しさん:02/07/21 02:11
>>34 stdexceptをincludeしても結果は同じでした。
36 :
istreambuf_iterator:02/07/21 14:15
/*
「Effective STL」p124 のサンプルをみながら打ち込んでみたけど、
VC++6.0 ではエラーになってしもた。鬱…。
*/
#include <fstream> // std::ifstream, std::istreambuf_iterator<>
#include <string> // std::string
#include <stdio.h> // puts()
int main()
{
std::ifstream ifs( "a.cxx" ) ;
std::istreambuf_iterator<char> begin( ifs ) ;
std::istreambuf_iterator<char> end() ;
std::string str( begin, end ) ; // 1 番目の引数を 'class std::istreambuf_iterator<char,struct std::char_traits<char> >' から 'const char *' に変換できません。
puts( str.c_str() ) ;
return 0 ;
}
37 :
istreambuf_iterator:02/07/21 14:17
ロジックの大半は、スクリプトではなく
ビジネスオブジェクトになければなりません。
この設計パターンに従えば、将来に備えることができるでしょう
> std::istreambuf_iterator<char> end() ;
std::istreambuf_iterator<char> end ;
ちなみに、VC6ではエラーってことは、
どのコンパイラなら通ったの?
俺の知る限り、
>>36のソースが通るコンパイラは存在しない。
>>36 に
>>38 の変更を入れた後の話だが、
STLport を入れればコンパイルできる。
リンクできなかったけど。
>>40 それはアンタの環境がおかしいんじゃないの?
STLPort4.53だと普通にコンパイル、リンクできるが。
あ、ごめん、STLportのせいみたいだった。
リンクできないのは漏れの環境がおかしいからです。
スタティックだとリンクできた。
ダイナミックだと出来なかった
以上
STLPortを使えということですか…。VC++6は古いからなぁ。鬱。
鬱、鬱、うっとおしいんだよ。
STLPortを使ってもアンタの出したソースは通らないんだよ。
新しいタイプのアンチVC6か?おまえは。
>>46 ほらよ
#include <fstream> // std::ifstream, std::istreambuf_iterator<>
#include <string> // std::string
#include <algorithm>
#include <stdio.h> // puts()
int main()
{
std::ifstream ifs( "a.cxx" ) ;
std::istreambuf_iterator<char> begin( ifs ) ;
std::istreambuf_iterator<char> end ;
std::string str;
std::copy( begin, end, std::inserter(str, str.end() ) ) ;
puts( str.c_str() ) ;
return 0 ;
}
( ゚д゚)ポカーン
>>50 たまたま知ってたからっていい気になるなよ!
( ゚д゚)ポカーン
なんで教えてもらった奴が偉そうなんだ?
>46, >50
誰だおめー?
>48
さくとす。
54 :
デフォルトの名無しさん:02/07/22 04:32
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
| Standard Template AGE. |
|___________|
∧∧ ||
( ゚д゚) ||
/ づΦ
55 :
デフォルトの名無しさん:02/07/22 04:45
イテレータ使えば30秒で書けるのにファンクタにしようとして数時間かかる罠
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
| 標準 雛型 上昇 |
|___________|
∧∧ . ||
(´∀`).||
/ づΦ
×ベクトル
○ベクター
◎ヴェクトゥァー
ペ久夕一?
×ペク卜ノレ
×ペク夕一
×ワ"τ久卜η了一
class T{
public:
static void Hoge(int i ){std::cout << i << std::endl;}
};
こんな風にstaticしかないクラスのメンバをfor_eachなどで使うには
どうすればいいの??
std::ptr_fun<int, void>(T::Hoge)
>>60 for_each(b,e,T::Hoge);
ではないの?
真・dat落ちストッパー。。。( ̄ー ̄)ニヤリッ
65 :
デフォルトの名無しさん:02/07/30 20:42
引数3つに対応しているbind*がないのでfor_eachが激しく使いにくいんですが
どうすればいいですか
boost::bind
しかし、boostのはbinary_function/unary_functionを継承してないから使いづらい
>>66 何処らへんで unary_function/binary_function継承してないと使いづらい?
とりあえずboost入れてみようと思ったがcygwinでデフォルトのインクルード
ディレクトリかえるのどうやるかわからんから、mingw使おうと思ったけど
楽しようと思ってDev-C++いれたらcppの関連付けかえられてしもうたぁーーー
>>68 デフォルトの検索パスを変更するなら、specs ファイル書き換える。俺は明示的に
-I で指定する方が好みだが。
/usr/lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs
71 :
デフォルトの名無しさん:02/07/31 13:19
合成関数を作るアダプタって用意されてないよね?
boost::compose*
>>71 標準STLではありませんが、なにか?
って書くとイヂワルなので…、
一応SGI STLではfunctionalにunary_composeつー
もんが用意されているらしい。boostについては…
まだ使ってないのでスマソ。
SGIをあまり使う必要が無ければ自作したほうが
ラクかと。
なるほどSTLportを使っているからSGIはナイスだ
boost::composeも見てみたらちょっとネーミングが…
boost::bindをみてみたら代用できるようで驚きだ
>>75 ネーミングって?
compose_f_gx_hxとか?
コレって混成方法を表して居るんだから、
SGI STLの奴より使い出があると思うが。
そうそうそれ、boost::composeの作者とは感性があわない
>>71 最初は俺も感性あわないと思ってたけど
f_gxやf_gx_hxやらf_gxyやらf_gx_hyとかって書いたほうが
1や2って書くよりも解りやすいと思うよ
79 :
デフォルトの名無しさん:02/08/04 18:14
話題ないな
面白いコンテナやアルゴリズム紹介して
#include <iostream>
#include <vector>
#include <boost/any.hpp>
void main()
{
std::vector<boost::any> v;
boost::any iany(10); //int
boost::any dany(10.102);//double
boost::any sany("hogehoge"); //char*
v.push_back(iany);
v.push_back(dany);
v.push_back(sany);
std::cout << boost::any_cast<int>(v[0]) << std::endl
<< boost::any_cast<double>(v[1]) << std::endl
<< boost::any_cast<char*>(v[2]) << std::endl;
}
毎度毎度思うけどこんなanyとかって作る人は一体
どういう考えしてるんだろうなぁ
なぜanyはoperator T()ではなくて外部にany_castを作ったのだろう?
(違いはstatic_castを記述するかany_castを記述するかだけだが)
いずれにせよ代入は簡単だけれども使うときに
キャストを(正しく!!)書く必要があるから結構大変
>>81 template<typename T> operator T() { return any_cast<T>( *this ); }
みたいなもの、ってこと?何だか思わぬところで思わぬcastを
されてしまいそうでかえって使いにくい気がする。
83 :
デフォルトの名無しさん:02/08/09 02:29
保守
関係ないけど、
なんでCの次なのにC++
(プラスが2つ)なの?
インクリメントしてんだよ。
なんで++Cじゃないの?
>>85 ソートしたときに C の次に来ないから。
89 :
デフォルトの名無しさん:02/08/09 19:48
Exceptional C++を読んでから、例外が恐くてvectorも
気軽に使えない・・・こんな洩れは逝ってよしですか?
>>91 恐れることは山ほどあります。
insertやeraseが中途半端で止まったら対策が面倒とか、
最後の頼みのclearやswapで死んだら打つ手無いじゃんとか。
vectorに皮かぶせたコンテナ作ろうとしたりすると、その辺りが
気になって気になって。
93 :
デフォルトの名無しさん:02/08/10 09:40
VC6 当時ならともかく、今の実装はまず大丈夫だが。
そんなに心配なら、うだうだ言う前に実験しろ!
結果が気に入らなければ、自分で作れ!
94 :
デフォルトの名無しさん:02/08/10 23:00
ぶっちゃけたはなし、そこまで気使って作らないことがおおいっすね。
>>92 スタックオーバーフローが怖くて関数も気軽につかえない口ですか?
ぶっちゃけたはなし、例外使ったこと無い。
ループの中で毎回チェックしたほうがコストがかかると思うんだけど
ほとんどの場合はどっちを選んでも誤差の範囲でしょ
>>97 いや、普段は戻り値まんせーなのと、STLでは成功するものだという思いこみ。
>>99 自分が例外を扱わないのに、STLの内部で例外使われていると、なんとなく
悔しい気分になりません?
そういやSTL使うと-GX付けないと文句言われるな
VC++ローカルな話でスマソ
>>100 別にならないよ。
でも、例外だしてくれる奴を無視してると、
あ〜STLとC++の能力を半減させてるなあと思ってしまふ。
>>100 例外で勝手に死んでくれるから便利じゃん
>>101 STL 内部でメモリアロケーション田尾の失敗したときに、例外投げてくるからねぇ。
C++ から例外を取ったら、かなり煩雑な書き方を要求されることになるのは間違
いない。
(まー C に時代が戻っただけ、という気もするが)
for(map<string, class WordFromDic*,less<string> >::iterator i=HashDic.begin();
i!=HashDic.end();i++){
delete i
}
106 :
デフォルトの名無しさん:02/08/13 11:10
↑すみませんまちがえました
class t = new WordFromDic();
HashDic["test"] = t;
などなど・・・
としたあとで
for(map<string, class WordFromDic*,less<string> >::iterator i=HashDic.begin();
i!=HashDic.end();i++){
delete i
}
となったときにHashDicが所持しているWordFromDicクラスへのポインタを
deleteする方法ってどうやるのですか?
107 :
デフォルトの名無しさん:02/08/13 11:31
>>106 iterator を delete するな!
delete i;
下
delete *i;
もし、ポインタ*を*deleteしたいのならばHashDic.erase(i);で破棄できる。
HashDicが所持しているWordFromDicクラスへのポインタにdeleteを適用して
ポインタの示しているオブジェクトを破棄したいならdelete i->second;
delete i->secondでコンパイルとおりました!
i->second...?の意味は良くわからんですけど
これで
WordFromDic t = new WordFromDic();
しか部分が消えていれば目的達成です。ありがとうございます。
どうやって消えているか判断する気なのか
111 :
デフォルトの名無しさん:02/08/13 13:09
横レスだが前置インクリ使えよ。
>>109 横レスだが
>class t = new WordFromDic();
?
>>110 VC++なら_CrtSetDbgFlagを使ってメモリリークを検出できるが、
gccとかC++Builderにはこんなのあるんかな。
>>114 operator ::new と ::delete に細工すればいい。
>>114 C++BuilderはPRO以上ならCodeGuardがついているよ。
117 :
デフォルトの名無しさん:02/08/13 18:33
vectorとかって、clear()したときに要素のデストラクタが呼ばれる/呼ばれないは
きちんと定義されてるの?
>>117 もちろん。そもそも vector って値ベースのコンテナだし。
119 :
デフォルトの名無しさん:02/08/13 18:42
>>118 117じゃないけど、STL始めようとおもってる初心者です。
便乗させてください。
clearのとき、デストラクタは呼ばれるのですか?
値ベースってことは、ポインタを格納することはできないのですか?
>>119 ポインタの「値」を格納することはできる。
vector <int*> v;
と定義したら v がスコープから外れる場合に int* を delete はしてくれない。
とりあえず STL の入門書を読んだ方が良いと思う。まじめに解説を始めると
書籍で数十ページになる内容だから、ここでやりとりするのは無理だ。
>>120 親切にありがとうございます。詳しいことは入門書で調べてみますが、
vectorのデストラクタ(と呼ぶのかな?)ではclear()のようなメモリ開放の処理は行われないのですね。
vector <int*> v;
をクラスメンバとした場合、クラスのデストラクタでv.clear()すれば
OKってことですか?
それだけ教えてください。
>>121 ぜんぜん違う。
clear()と同じことはvectorのdestructorでも呼ばれる。
格納物がポインタならば、ポインタ自身は開放されるがその指す先は関知しないというだけだ。
ポインタ自身の開放ってのはつまり、32bit pointerならば4byteの開放ね。
>>122 親切に説明してくれているのに
よくわからないので出直してきます。スマソ。
>>123 int **pp = new int*;
int *p = new int;
*pp = &p;
としておいて、
delete pp;
としてもpの指す先が解放されないのと同じ。ニュアンスは異なるけど、
言いたい事は伝わりますか?
>>124 親切にありがとうございます。
わかった気がします。
clear()じゃ、delete int*に相当する処理が行われないということですよね?
int *n = new int;
v.push_back(n);
v.clear();
だとすると、nはメモリ上に残ったままになる・・・と。
この場合、イテレーター使って全要素にdeleteしないといけないの??
>>125 そうなりますね。
別のケースで言えば、リスト構造のデータがある時、初期ノードを削除
してしまってもそこからつながったデータは残ったままになるのと同じ
ですね。
>>126 なんか面倒・・・。
一気にdelete呼ぶ方法はないかな?
boostのshared_ptrとか使えば気にしなくていいの?<これも勉強中です
質問ばっかですいません。
>>127 一気にdelete
template<typename T> struct deleteer {
void operator()( T* ptr ) { delete ptr; }
}
for_each( v.begin(), v.end(), deleter<int>() );
とかやるよりは
> boostのshared_ptrとか使えば気にしなくていいの?<これも勉強中です
こっちが正解。
>>128 ありがとうございます。理解できました。
でも、boostのビルドに失敗してるし>自分
http://www.dodgson.org/lab/hat/boost_intro.html のとおりにやってるつもりなんだけど、
jam -sBOOST_ROOT=. -sTOOLS=msvc
ってやると
warning: unknown rule boost-build
don't know how to make all
...found 1 target...
...can't find 1 target...
とでてしまいます。
ビルドする必要はない。
どうしてもビルドしたいなら、threads/regex++のディレクトリでmakeしなさい。
ついでに言うと、boostはVC6じゃビルドできない
>>93 蒸し返すようですが、例えばreserve()を呼んだ後はpush_back()が
例外を投げない(もちろんコピーコンストラクタは例外を投げないとして)
とか、そのくらいまで(実装依存でなく)標準で保証されているのですか?
それとも、そういう保証が欲しければ自作することになりますか?
boostって、コンパイラオプションにヘッダファイルの場所を指定するだけ
じゃ駄目なの?
threadやregexとか使わなきゃそれで十分だろ。
>>136 あとは STLport 付属の iostream を使う場合には、ライブラリをリンクする
必要があるな。VC++ とかだと #pragma が良きに取りはからってくれるけど。
>>137 必要ない。
必要なのはstlport側だろ?
boost側でリンクする物は一切無いよ。
STLマンセー
>>133 明示的に標準が要求しているのは、push_back() で例外が投げられた場合、
その呼び出しが無効になることだけ。
無効になるとは、コンテナの内部要素に変更が起こらないということだ。
この保障だけで十分安全に push_back() を使うことができると思うが。
もちろん実装が適切に構築されているかどうかは別の話だ。
だいたい標準はガンガン例外を投げろという立場だから、そんな後ろむきな保障の仕方はしていない。
>>141 規格で保証されてるのは
1. capacity() は reallocation なしで保持できる要素数を返す。
2. reserve(size_t n) を呼び出すと capacity() な n 以上になる。
だから、結果的に push_back() で例外は飛んで来んと思うが。何か見落としてる?
143 :
デフォルトの名無しさん:02/08/19 17:31
>>142 >無効になるとは、コンテナの内部要素に変更が起こらないということだ。
>この保障だけで十分安全に push_back() を使うことができると思うが。
全然安全じゃない。複数のオブジェクトをnewして、順番にポインタを
push_back()するコードを書いたら、vectorに入るオブジェクトと
入らないオブジェクトが出て来る。
144 :
デフォルトの名無しさん:02/08/20 04:18
STLマンセーなのは良いんだけどさ、
ちゃんと例外キャッチして欲しい・・・。
適当にgoogleって眺めてたんだけど、
ちゃんと例外使ってるソース見つけられなかったよ。
誰か参考になるような良いソース知りませんか?
>>144 例外のキャッチとSTLに何の関係があるの?
普通の例外のキャッチとなんか違う?
>>145 例外が起こるタイミングが予測しにくいところ。
map[str]みたいに書くと、一瞬普通の配列アクセスみたいに見えるから、
例外処理を忘れると後で気付きにくいところ。
>>146 それも例外全般の話で、STLに限ったことじゃないよな。
map[str]での例外に注意が行くかどうかの注意力は、
人のソース見て身につくもんじゃないとおもうけど。
でもSTLで特に間違いやすいのは確か。
もうポクの人生も例外がでてしまいそうです...
俺はbad_allocだけcatchしてる。
>>145 良い感じのネタフリだったのに、そんなレスすんなよ。
>>150 じゃぁさ、「そんなレス」の替わりに、145の時点で「俺はbad_allocだけcatchしてる」って
書いてあったら、有意義な方向に話が進んだと思うか?
そんなわけないとおもうけどなぁ。
>>148 なんか理由挙げれる?
ちなみに147=145。
Error:例外:bad_lang_japaneseが発生しております...
アロケートに失敗した時にbad_allocを投げるのは、
STLとnewのどっちの仕事なんでしょうか?
もしかして処理系の実装依存?
newのお仕事です。newが失敗したらbad_allocを投げることになってるもの。
ちなみに実装依存ではありません。VC++がbad_allocを
投げないのは「バグ」です。
いいえ、bad_allocなんて投げません。0を返します。
>>157 違いマース、C++の昔の仕様に準拠してるだけデース。(マジ
まぁ、VC++6.0に関しては時期的に微妙なところがあったからな。
そっから次までが長すぎただけで。
javaみたくcatchを書かないとコンパイルではねられるようにはならないのかな・・・?
void func() throws exception;
みたいな書き方はC++にもあったような気もするが・・・
詳しい人レス希望.
>156
> newのお仕事です。newが失敗したらbad_allocを投げることになってるもの。
言われてみればそうですね。
STLportに入れ替えても例外来なかったんで気になってたんですよ。
今まで通り _set_new_handler で誤魔化しながら使うしかないのか。
>>161 その関数がどの例外を投げるのか明示
だったと思うけど使ったことないや。
>>161 C++ の例外指定は、コンパイル時に強制チェックが入らないから、あまり
意味がない。
>>161 確かにありますけれども。
void foo() throw(A, B)
{
}
のように書いて、foo が A, B 以外の例外を投げないことを保証する。
もしそれ以外の例外を送げようとしたら、unexpected が呼ばれる。
例外指定なしに比べて unexpected を呼ぶコードが付くから、コードが肥大化するかもしれないのに対し、
呼び出し側で何か最適化に利用出来るわけでもなく、あまり意味がない。
assert な気持ちで書くのが良いんじゃないかしら。
>>162,163,164
呼び出し元でcatchを強制できるわけじゃないのね・・・・
レスさんきゅです.
166 :
デフォルトの名無しさん:02/08/24 18:22
throw()なら最適化に利用できるよ。
でも、変な例外投げそうなら、せめてwarningくらい出して欲しい。
templateがあるから、簡単にいかないのは分かるけど。
167 :
デフォルトの名無しさん:02/08/25 18:42
データ保持にlistを使ってツールを作っています。
リスト長は、最大でもせいぜい20個位なのですが、リストの削除や追加を
一分間に20回ほども繰り返し、8時間ほど常駐されるツールです。
そこで質問なのですが、このように頻繁な追加削除を行う場合、
メモリ空間はどんどん汚れていってしまうのでしょうか?
いつもはあまり気にしないのですが、今回は常駐ツールと言うことで
悩んでいます。つまらない疑問で恐縮ですがよろしくお願いします。
>>167 > メモリ空間はどんどん汚れていってしまうのでしょうか?
意味不明だが…
>>168 えっと、追加削除のたびに、確保されていたメモリが
小さな欠片として、散らばってしまうのかなと思ったんです。
解決方法は難しく無さそうですが、後学のためといいますか、
listが上手いこと処理してくれるなら、信頼のおけるlistを
使った方がいいなと思いまして…。
>>170 信頼のおけるlistをどうやって作ろうと思っているかちょっと気になる。
と、書いているうちに……すいません。
>>169 返答ありがとうございます。良かった、この位なら大丈夫なのですね。
安全で安心なlistでいけてホッとしています(*´ω`)=3ホッ
>>171 あ、信頼の出来るlist=STLのlistという意味ですー。
自分で、例えば未使用リストをプールして置くようなのを作るよりは、
信頼の出来るSTLのlistで行った方が、安全だし早くできるなと。
連カキコすいませんです。
>>173 メモリ空間が多少乱れても、ページング処理により大勢に影響ないと思う。
メモリ監視ツールとかでどのくらい無駄になっているか調べてみたら?
追加削除でどうしてもメモリ量が増えつづけるなら、
予めリザーブ領域を十分に用意しておけば大丈夫じゃないかな。
>>174 なるほど…ページング処理…そしてリザーブ多めでOKですか。
最近ようやくハードを意識したプログラムに目覚めたところでして、
こういったキーワードを教えて頂けるのは本当に助かります。
これから詳しく調べてみたいと思います。レスありがとうございました。
>>170 stop-and-copyガベージコレクションをするとか。
std::listだったら、allocatorを変更して
プールした領域からメモリ確保するようにすれば充分かと
つーか、そもそもたいていの実装でmalloc/free、new/delete自体がプールしてるはずだが。
有名な「free/deleteはOSにメモリを返さない」って奴。
>>178 実装によっては、さらに STL コンテナの allocator でもプールしてたりする。
STL の一部のコンテナってプールすることが明示されてなかったっけ?
181 :
デフォルトの名無しさん:02/08/26 22:17
vector とか list オブジェクトをコピーしたときって、
格納されている要素オブジェクトも全部コピーされるんでしたっけ?
string みたいにバッファは参照回数付きで共有されるなんて
ことはない?
>>181 そういう実装を作ってもいいんじゃない?普通はコピーするだろうけど。
stringも、実際は共有してても、あたかもコピーしているかのように動作しなければならないはずだし。
いや、自分で作るのはちょっと (^^;
g++ と VC++ で提供されている STL の実装では、このあたりが
どうなっているかを知りたかったのです。
もし、要素オブジェクトもコピーされるなら、vector オブジェクトの
ポインタを shared_ptr かなんかで包んでしまうとかしますので。
vectorやlistは要素をコピー元と先で、別々に操作したいからなぁ。
要素も全部コピーでいいと思う。
参照渡しじゃだめなの?
>>185 > vectorやlistは要素をコピー元と先で、別々に操作したいからなぁ。
要素の操作は、vector や list オブジェクトを介さずに行うことが
できるから、たしかに全部コピーしないとまずいですね。
> 参照渡しじゃだめなの?
vector オブジェクトを包含する別のオブジェクトがあって、
それのコピーをしたいんです。参照で持たせるのはちょっと
使い勝手が悪いんで、やはり shared_ptr あたりを使うことに
しようと思います。
というか、COWでデータを共有したいならbasic_string<Hoge>使ってもいい気がするが?
rope<Hoge>とかも
誰か助けてください。
BCC5.5.1+XPで以下のプログラムを実行すると、Ctrl+Zが1発で終了すると思うのですが、
2発必要です。VC.NETでは問題ありません。
BCCのバグでしょうか?検索しても見つからないのですが。
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
int main()
{
vector<char> v;
copy(istream_iterator<char>(cin), istream_iterator<char>(), back_inserter(v));
for(vector<char>::iterator iter = v.begin(); iter != v.end(); ++iter)
cout << *iter << " ";
cout << endl;
}
もちろん、代替策はいくらでもあるのですが、気持ちが悪いのです。
バグなのか私のカンチガイなのか。
どなたかよろしくお願いします。
Rogue Wave Stlのバグ(仕様?)っぽい
Stlportだとちゃんと終了する
192 :
デフォルトの名無しさん:02/08/27 18:47
ちょっと質問
VC6 + STLPort 4.5.3 でメモリ確保失敗時にbad_alloc例外を
投げるようにするには、どうすれば良いのでしょうか。
main() {
try { std::vector<int> v(1000000000); }
catch ( std::bad_alloc & ) { cout << "OK" << endl; }
}
オプションの例外処理は有効にしています。
現状では、コンストラクタ内のfillがNULLポインタに触って
Access Violationで落ちてしまいます。
どのようにすれば、例外を投げてくれるのでしょうか。
_set_new_handler()
すみません
説明が足りませんでした。
_set_new_handlerは使えないんです。
実は、自作のライブラリ内で使いたいので、メイン側に影響を与えるような
変更は極力避けたいのです。
どうも、_set_new_handlerはDLL越しにでも効いてくるみたいなので
出来ればカスタムアロケータで対応したいのですが。
自前のアロケータを書けば良いのは分かってますが、設定か何かで
ちゃちゃっと出来ないですか。
>>189>>191 本当だね。Rogue waveのバグだ。
Borland-C++ 5.6なんだけど、STLPortでは正常に動作し、
#define _USE_OLD_RW_STL をするとおかしくなる。
>>194 _set_new_handlerはDLL越しにでも効いてくるみたいなので
だったらdll側ではmsvcrtを使わずにスタティックリンク汁
>>197 なるほど、言われてみればそうですね (^^;
CPPUNITでテストするのに、同じライブラリを呼ばせるため
ダイナミックでリンクしてました。
個別クラスのテストはダイナミックでやって、リリースは
スタティックにすればいいのかな。
素早いレス、どうも有難うございました。
199 :
デフォルトの名無しさん:02/08/28 08:35
ユーザー定義型の type_traits を自分で設定したいなぁ
と思うんですけど、ソース読んで
template<> __type_traits< ...
とか書くのが正解なんでしょうか?
もうちょっとマシなやりかたはあったりしませんか?
Exceptional C++ にディフォルトの type_traits を継承して
必要なものだけ再定義しなさい、と書いてあった気がする。
外してたらすみません。
201 :
デフォルトの名無しさん:02/08/29 00:17
reverse_iteratorをつかって、list::insert()を行うにはどうすれば良いのでしょうか?
普通のiteratorじゃないと弾かれてしまってキャストも効きません・・・。
VC++6.0付属のSTLを使っています。どうか宜しくお願いします。
>>201 reverse_iterator::base()
>>202 見事にうまくいきました(´Д⊂
レスありがとうございました。
>>200 デフォルトの type_traits をもってくる方法が胡散臭いんですよ。
std::type_traits とか、 ::__type_traits とか。
どんなメンバがあるのかも、ソース読まないと分からないようですし。
type_traits を作ってる側から、「自分の奴がほしいなら、こうやって定義してね」
っていうマクロでもあるといいんですが。
度々すいません、またリバースイテレータの使い方で悩んでいます。
>>202で教えて頂いた方法を、erase()に使ってみたのですが、
どうしても上手く逝かなくて…、簡略化するとこんな感じです。
main(){
std::list<int> lst;
lst.push_back(0);
lst.push_back(1);
lst.push_back(2);
lst.push_back(3);
lst.push_back(2);
std::list<int>::reverse_iterator r_it;
for( r_it=lst.rbegin(); r_it != lst.rend(); r_it++ ){
if(*r_it == 2 ){//後ろからソートし、最初の2をリストから削除したつもり
lst.erase( r_it.base() );
}
}
std::list<int>::iterator it;
for( it=lst.begin(); it != lst.end(); it++ ){
std::cout << *it << ' ';//0 1 2 3と出力して欲しい
}
}
VC++6.0付属のSTLで、実際にはエラーが出てしまいます。
リバースイテレータの正しい使い方を教えて頂ければ幸いです。
と、すいません。あげさせて下さい。
if(*r_it == 2 )
{
lst.erase(--r_it.base() );
break;//最初の2が見つかった時点で処理を打ち切る。
}
何故こうする必要があるのかはEffective STLに書いてある。
要するに消去に関してはr_itとr_it.base()は等価ではないということだが。
つーか、この処理のどこにもソートは関係ないと思うが。
>>207 レス遅れてすいません。なんかネットに繋がらなくて・・・YBBめヽ( `Д´)ノ
おかげさまでうまくいきました。なるほど、等価で無いのですね・・・。
>ソート break
なはは、なんでこんなこと書いちゃったのだろ(もちろんアホだから)…お恥ずかしい。
reverse_iteratorの用法は、不思議とネット(日本語)には無くて…本当に助かりました。
Effectiveシリーズはやはり全部必読なのですね…。返答ありがとうございました。
真・dat落ちストッパー。。。( ̄ー ̄)ニヤリッ
ネタがないのでひと休憩...
こんなんあったら便利orこんなん作ったよ
ってテンプレってある?
コピー演算子
std::basic_ostream::operator=()
ってSTL標準じゃないの!?
STLPortには入ってなかったんだが。
ってか、正しくは「代入演算子」か?
あと疑問に思ったのだが、代入演算子は
なければ勝手に作成されるはずだが、
それもされない。
VC6+STLPortだと作成されずにゴルァされる。
標準にはないね。
> それもされない。
void operator=(const _Self&) {};
されてるから。
>>212-213 レスTHXです。
標準じゃなかったのか…使いやすかったのに…。
>void operator=(const _Self&) {};
これって、basic_ostream::sentry内で定義さ
れてるのじゃなかったっけ?
今手元にないので、帰ったらもう一度確認
してみます。
質問です。
int key;
int data1, data2;
というデータを set か map で扱う場合、そのどちらを選択するかは
「データの構造体がキーを含むものか?」ということを分析して
判断するのものしょうか?
それともどちらかを使ったほうが効率がいい、ということがあるのでしょうか?
1.
----------------------------------------
typedef struct A {
bool operator<(const A& rhs) const { return (key < rhs.key); }
int key;
int data1;
int data2;
} A;
typedef std::set<A> HOGE;
----------------------------------------
2.
----------------------------------------
typedef struct A {
int data1;
int data2;
} A;
typedef std::map<int, A> HOGE;
----------------------------------------
>>215 >データの構造体がキーを含むものか?
も一つの選択材料だと思う。
他にも、「データの変更を伴うか?」とか。
効率については特に違いはないと思いま
再度ヘッダ確認してみたのですが、
void operator=(const _Self&) {};
が定義されているのは
basic_ostream::sentry内で
basic_ostream内では定義されて
いませんでした。
またVC6でデフォルトの代入演算子が
生成されない条件は「クラスを引数とする
代入演算子が定義されていない」こと
らしく、デフォルトが生成される条件には
当てはまっているんだが…。
ワケワカラン...
とりええず、
>標準にはないね。
情報ありがとうございました。
>>217 > void operator=(const _Self&) {};
> が定義されているのは
> basic_ostream::sentry内で
おうホントだ。失礼。basic_ostreamじゃなくて
派生元のios_base側で禁じてあるようだ。
>>218 >ios_base側で…
その手があったか。ios_baseまで
確認していなかった。
確かにVC6のSTLでは、
ios_base& iosbase::operator()
が定義されているのでデフォルト生成
される理由の説明がつく。
???となるとどっちがSTL準所なんだ?
VC6STLの方が糞っぽい気が…。
帰ってからSTLPortも確認してみます。
わざわざ見なおしていただいてありがとう
ございました。
>>215 あと、効率を無視出来るときは、mapの方が配列演算子使えるから読みやすく書けるってのもあるよ。
>216,220
確かに「データ変更を伴うか?」というのも重要なファクターですね。
見落としていました。
ご回答ありがとうございました。
>>220 >配列演算子
あ、コレも重要なファクタだね。
忘れてますた。
mapのoperator[]は慣れない時に失敗した覚えが…。
あれって要素の有無を調べるのには使えないんだよね。3時間くらい無駄にした。
>>210,219
iostream は STL じゃない、よ、ね?
>>224 ???
iostreamはれっきとしたSTL、で、は?
旧iostream<iostream.h>は非STL。
新iostream<iostream>はSTL。
>>225 ハァ?
iostreamは標準C++ライブラリの範疇だが、STLではないぞ。
ストリームのイテレータがあることで混同しているのかも知れないが。
>>226 (゚д゚) ハァ?
ナニ言ってんのコイツ?
(;・;Д;・;) ハッ!!!
あ!
iostreamはSTLじゃなかった。
iostream=C++標準ライブラリ ○
iostream=STL ×
髭...
STLが標準に取り込まれてしまった現在、STLとそれ以外を分ける必要ってあるの?
情報を探すときには、分かれてるのを知ってないと的外れなところを漁ってしまったり。
質問です。
class T{
vector<int> aaa;
vector<double> bbb;
};
のようなクラスでコンパイル時にコンテナを換えたいようなとき、
template <typename Container1, typename Container2>
class T{
Container1 aaa;
Container2 bbb;
};
T< vector<int>, vector<double> > foo1;
T< list<int>, list<double> > foo2;
とやらずに
template <templatename Container>
class T{
Container<int> aaa;
Container<double> bbb;
};
T<vector > foo1;
T<list > foo2;
という感じの事はできないんでしょうか。
下の例はあくまでイメージですけれど。
>>230 > template <templatename Container>
標準 C++ なら、
template <template<typename> class Container>
みたいに書けるけど、VC++ はこの書き方をサポートしてないんだよね。
>>231 VC7 はサポートしてるが、デフォルト・テンプレート引数に対応してないので
どっちにしろ、STL コンテナには使えない罠
>>231 > template <template<typename> class Container>
g++でコンパイルできました。
gccを使っていますので問題ありません。
こんな書き方ができるとは知りませんでした。
もっと標準C++を勉強してみます。
ありがとうございました。
template<template<class T> class Container>
{...};
こういう書き方も聞いたことある。
VC6しか入れてないので正しいかどうか確認できませんが…
>>234 勉強のために Modern C++ Design を買ってみたんですが
> template<template<class T> class Container>
のTは省略可能と書いてありました(P.11)
実際 T は使わないからそれでもよいみたいですね。
>>235 わざわざTHXです。
>Modern C++ Design
買ったんですか。私も今度買う予定です。
噂では異常変態的参考書とか…
237 :
デフォルトの名無しさん:02/09/17 07:32
std::mapでデフォルト値をT()以外にすることってできませんか?
std::map<std::string, int> m;
int i = m["NOTEXIST"];
としたときにi==0以外にできるような。
class Integer {
public:
Integer(): val(1) {}
operator int() const { return val; }
operator =(int v) { val = v; }
以下略
private:
int val;
};
std::map<std::string, Integer> m;
int i = m["key"];
とか
>>238 ども。
整数だけならこうかな?
デフォルト値が型名に入るのが使いにくそうだけど
template<class T, T N>
class defaulted_number {
T value;
public:
defaulted_number<T,N>(): value(N) {}
defaulted_number<T,N>(const defaulted_number<T,N> &t): value(t.value) {}
defaulted_number<T,N>(const T t): value(t) {}
operator T() const { return value; }
T &operator=(const T v) { value = v; return value; }
};
240 :
デフォルトの名無しさん:02/09/18 20:29
前スレgoogleで検索してここに辿り着いたのですが、
293 名前: STL勉強中 投稿日: 02/01/20 08:11
以下のコードがコンパイルエラーになってしまいます。
void foo(const int &i, const char *s)
{
cout << s << i << endl;
}
int main()
{
int d[] = {1, 2, 3, 4 };
vector<int> v(d, d + sizeof(d) / sizeof(int));
for_each(v.begin(), v.end(), bind2nd(ptr_fun(foo), "foo:%d"));
}
294 名前: 名無しさん@Emacs 投稿日: 02/01/20 12:08
>293
何故ダメなのかはちょっと分からないんだけど, foo の引き数を
const int& から int に変えると g++ 2.95.3 ではコンパイル通るよ.
実際,int とかは参照よりも値渡しの方がパフォーマンスいいし,
参照の必要が無いんなら int にしてみては?
# 必要があるんだと・・・どーすりゃいいのかねぇ.
実際、このケースで、intの代わりに重い構造体への参照使う必要があるのですが
……どーすりゃいいんでしょう?環境はgcc 2.96です。
つーか、何故に参照じゃダメ?
# 過去ログの見落としし等あればスマソ
STL猛者の方、ご教授をお願いします。
>240
293, 294が前スレのログで、
最後のブロックが私の質問です。
空白省略されちまいました。見づらくてスマソ
std::ptr_fun<int,char*,void>(foo)
とする。
理由は、binder2ndの
typename _Operation::result_type
operator()(typename _Operation::first_argument_type& __x) const {
return op(__x, value);
}
ここで参照の参照になってしまうから。
>242
>ここで参照の参照になってしまうから。
あの〜これは既に参照型として使われているから、
わざわざ引数を参照にして関数を作る必要はないということなのでしょうか?
void foo(const int &i, const char *s) → void foo(const int i, const char *s)
でいいって事?
それとも、
>std::ptr_fun<int,char*,void>(foo)
>とする。
そのまんま
for_each(v.begin(), v.end(),
bind2nd(std::ptr_fun<int, char*, void>(foo), "foo:%d"));
と書くと、やっぱり
cannot convert `void (*) (int &, char *)' to `void (*) (int, char *)
と怒られてしまいました。
スマソ、全然理解が足りない。
明日、Effective STLを買いに走ろう。
>>242は一生に一度あるかないかの逆ナンパをけりました。
合掌(´人`)
>>243 俺とはどうよ?
>>242 あー、おれも昔、同じ問題で引っかかったことがある。
そういう理由だったか。
しかし、だとすると bind2nd::operator() とかが参照型を
引数にしている理由が分からんな。
元になる関数 (foo) が参照型を引数にとっていれば、
first_argument も参照型になるし、もとが参照型でないとすれば、
それは参照型にしなくてもさほど効率が落ちないからであって、
やはり first_argument も参照型にする必要はない。
…ということにはならん?
>242
なんだ、勝手に参照型として判断してくれるのか。
なんかプログラマの感覚的にすごく分かりづらい……
>247
結構引っかかる人が多いようで、なんか安心した。
>もとが参照型でないとすれば、
>それは参照型にしなくてもさほど効率が落ちないからであって
どうやって区別しているんだろうねえ――。
無条件の参照型(intとか)は、かえって効率落ちるだろうし。
>>240-248 オメーラ、ホントにヴァカばっかだな。
天才のオレ様が糞みてーなオメーラに(略
と言いたいところだが、漏れも結構ハマったクチ。
んで本題↓。
どうやら作者は↓のようなことを想定して作ったと思われ。
class clsA //clsAクラス宣言
{
public:
int func(int n) //引数を1つとるメンバ関数
{
//do something...
return n;
}
}
//コンテナ内の全てのclsAに対してfuncを呼ぶ
void do_func(vector<clsA> &cont, int n)
{
for_each(cont.begin(), cont.end(), binder2nd(mem_fun1_ref(clsA::func), n));
}
このようなロジックを書いた場合に、
もし第1引数が値渡しになってしまうと、
binder2nd::operator()が呼ばれた時点でクラスが
コピーされてしまい、コンテナ内にあるclsA自体
にはfunc()が行われなくなってしまう。
…って解釈しているんだが。
>>243 お、オレとはどうよ? ハァハァ...
お前ら素直にポインタ使えって事でファイナルアンサーなんじゃ?
>>250 やはり納得いかん。そもそも mem_fun1_ref_t を
template <class _Ret, class _Tp, class _Arg>
class mem_fun1_ref_t : public binary_function<_Tp,_Arg,_Ret>; // _Tp を
ではなくて、
template <class _Ret, class _Tp, class _Arg>
class mem_fun1_ref_t : public binary_function<_Tp&,_Arg,_Ret>; // _Tp& ね
のように作っておけばよかったんではないか? そうすれば、binder2nd も
operator()(const typename _Operation::first_argument_type& __x) const;
ではなくて、
operator()(const typename _Operation::first_argument_type __x) const;
にできたと思うが。だいたい型の分からん関数引数に勝手に & を
つけるほうが間違いじゃないのか。どうよ。
253 :
デフォルトの名無しさん:02/09/19 10:38
そもそも、どうして
typename _Operation::result_type
operator()(typename _Operation::first_argument_type& __x) const {
return op(__x, value);
}
なんだ?
typename _Operation::result_type
operator()(const typename _Operation::first_argument_type& __x) const {
return op(__x, value);
}
だったら問題ないはず。(SGI版はそうなっている)
const性も保たれるし、標準では参照の参照は単なる参照として扱われるはず。
あと、vector::iteratorとchar *は同じとは限らない、ってのには
誰も突っ込まないのか?
254 :
hiraoka:02/09/19 10:44
237はたぶんmap::operator[]の理解が足りない。
240はboost::bindでok。
おもしろいなぁ。STLに振り回されている人が沢山いる。
人間が馬鹿なのかSTLが難しすぎるのか。どっちだろうなぁ(w
>>253 > 標準では参照の参照は単なる参照として扱われるはず。
そう扱ってくれてもいいと思うんだが、規格書をざっと見た限り、
参照の参照は許されない、という趣旨の記述しか見当たらなかった。
あと、gcc-3.2 だと引数に const がついているようだ。
std::mapは、存在しないキーを[]演算子でアクセスすると、そのキーとデフォルト
コンストラクタのpairの新しい値を挿入する仕様である。
だから、例えば m["NOTEXIST"] とした時点で、"NOTEXIST"と 0 のpairが
挿入されてしまう。
他の値を結びつけたければ、m["NOTEXIST"] = -1; のようにすればよい。
>>258 キーの存在確認には常に
find(key)!=end()
ってやる人?
>>259 そうしないと勝手に挿入されてしまうからなあ。
どこが間違ってるんでしょうか?
const int N = 100000;
struct insert_rand : public std::unary_function<double *, void> {
void operator()(double *d) {
*d = std::rand();
}
};
int main()
{
double ary[N];
std::for_each(ary, ary + N, insert_rand());
}
261です。
自己解決しました。for_each()が関数オブジェクトに渡すのはdouble *でなくて
doubleでした。
だから std::unary_function<double &, void> とすれば動きました。
うーんいまいちよく分からないんだよな〜。なんでdouble *じゃないんだろ。
>>262 配列なら double* が渡されるとすると、vector なら
vector<double>::iterator、listならlist<double>::iteratorが
渡ってきてしまうわけで、汎用の insert_rand なんてものは
作れなくなるわけだがそれでもよろしいか?
>>263 なるほど、ありがとうございます。
そのご説明ならよくわかります。
template <typename T>
struct insert_rand : public std::unary_function<T &, void> {
void operator()(T &d) {
d = std::rand();
}
};
みたいなものが作れなくなるわけですね。
いや、別にtemplate使わなくてもvector, list等から呼び出せる汎用ファンクタ
が作れるのか。doubleにハードコードされている事を除けば。
ふむふむ、STLはいろんな事を熟考して作られているんですね。
>>261 const int N = 100000;
int main(void)
{
double ary[N];
std::generate_n(ary, N, std::rand);
//std::generate(ary, ary + N, std::rand);
}
書く前にどのアルゴリズムが一番適確か考慮
した方がいいぞ。
>>252 う〜ん。長くなってしまうが…
そもそも *argument_type は
「引数の型情報」ではなく
「引数に渡される"生成可能な"型情報」
と解釈した方がいいかも。
もし *argument_type を「引数の型情報」(参照も可)
にした場合、
binder2nd<equal_to<int> >
は...
template<class T>
struct equal_to:binary_function<T&, T&, bool>{...};
//↑コピーのオーバーヘッドを避けるため参照(int&)
template<class Op>
class binder2nd:unary_function<Op::frist_argument_type, Op::result_type>
{
public:
...
protected:
Op operation;
//↑equal_to<int>のインスタンス
Op::second_argument_type value;
//↑参照型(int&)になってしまう。
public:
//↓コンストラクタ
binder2nd(Op& op, Op::second_argument_type v):value(v),operation(op){}
//↑第2引数はコピーではなく参照するのみ!
};
...となり、意図した動作ではなくなってしまう。
また、「引数に渡される"生成可能な"型情報」にした方が、
ユーザfunctorを作る際に自由度が増すからだと思う。
template<class Op> func(Op& op)
{
Op::argument_type val; //好きにしてン♥
...
}
とはいえ、確かに *argument_type =「引数の型情報」
にした方が名前通りの情報で納得できるが…。
誰か納得できる答えうp汁!
>>253 スマンコ。binder*は非変更(const)のfunctorですた。
変更を伴うアルゴリズムでは使ってはいけません。
訂正してお詫び(略。
>>266 261です。
丁寧なレスありがとうございます。早速試してみます。
Visual C++付属のSTLのvectorに関して教えてください。
typedef const_iterator _It;
vector(_It _F, _It _L, const _A& _Al = _A())
{insert(begin(), _F, _L); }
void insert(iterator _P, _It _F, _It _L)
{...
iterator _Ucopy(const_iterator _F, const_iterator _L, iterator _P)
{for (; _F != _L; ++_P, ++_F)
allocator.construct(_P, *_F);
return (_P); }
となっているのですが、(つづく)
template<class _It> ← 追加
vector(_It _F, _It _L, const _A& _Al = _A())
: allocator(_Al), _First(0), _Last(0), _End(0)
{insert(begin(), _F, _L); }
template<class _It> ← 追加
void insert(iterator _P, _It _F, _It _L)
{...
iterator _Ucopy(const_iterator _F, const_iterator _L, iterator _P)
{for (; _F != _L; ++_P, ++_F)
allocator.construct(_P, *_F);
return (_P); }
とすべきではないでしょうか?
ttp://www.dinkumware.com/vc_fixes.html のdequeを見ると同じような感じに修正されています。
これで動けば問題は無いのですが、vector<int>をコンパイルしようとすると、次のようなエラーが出ます。何がいけないのでしょうか。
error C2664: '_Ucopy' : 1 番目の引数を 'int' から 'const int *' に変換できません。
コンパイルされたクラスのテンプレートのインスタンス化 'void __thiscall std::vector<int,class std::allocator<int> >::insert(int *,int,int)' の参照を確認してください
でんでん分からず困っています。よろしくおながいします。
>>272 よくわからんけど、vector<int>でインスタンスを生成するテンプレートは
元々別に存在しているんじゃないでしょうか。
じゃないと、修正前にvector<int>が通るはずがありませんから。
つーか、修正する前は何が問題だったの?
275 :
デフォルトの名無しさん:02/09/20 14:55
>>271 というか、すでに修正済み。
template<class _Iter>
vector(_Iter _First, _Iter _Last, const _Alloc& _Al)
いうまでもなく、VC7で、だがね。
>>273,274
insertをtemplate化する事により、別のvectorのiteratorを渡して
insertできるようになる!のかな?というつもりだったのだが。
どうやら、template化した事により、多重定義されている別の
insert↓から呼ばれるのがinsert(int*,int,int)だと思われてしまうらしい。
iterator insert(iterator _P, const _Ty& _X = _Ty())
{size_type _O = _P - begin();
insert(_P, 1, _X);
return (begin() + _O); }
つーことで、(つづく)
dequeの修正を真似て次の用に変更した、
template<class _It>
void insert(iterator _P, _It _F, _It _L)
{_Insert(_P, _F, _L, _Iter_cat(_F)); }
template<class _It>
void _Insert(iterator _P, _It _F, _It _L, input_iterator_tag)
{size_type _O = _P - begin();
for (; _F != _L; ++F, ++_O)
insert(begin() + _O, *F); }
template<class _It>
void _Insert(iterator _P, _It _F, _It _L, bidirectional_iterator_tag)
{...
_Iter_catを使用してiteratorの場合にコンパイラーが区別できるようになる!?
のかな?よくわからん。
_Iter_catって初めてなんだが、なにもの?
親切な方、おねがいします。
VC6用のSTLPortを入れればすべてが解決するのでは。
sage忘れた……欝氏
>>271 マジレスするとだね、十中八九
vector<int> v(10, 10);
という、変数の初期化の際に
vector(size_t s, int v) // (個数,初期値)
ではなく
template<> vector<int>(int _first, int _last) // (反復子1,反復子2)
が呼ばれてしまうからだ。
Stroustrup 氏のC++3のP522にも書いてある、よく知られた問題だ。
俺もやったことがあるが、これを回避するのは結構めんどいぞ。
体育会系なノリでやっつけるなら、全ての整数型に対して
スペシャライゼーションを作ればいいんだが(シンデモヤラネエ)。
>>278 それができれば嬉しいのですが・・・
諸々の事情で、できればVC付属のを修正するにとどめたいと思いまふて・・・
>>279 よく分かんないんですが、コンストラクターの部分もdequeをみて
iterator使った個所を次のように変更済みです。
感覚的には(Wこれで対応できているような気がするんですが
不十分でしょうか?
template<class _It>
vector(_It _F, _It _L)
: _First(0), _Last(0), _End(0)
{_Construct(_F, _L, _Iter_cat(_F)); }
template<class _It>
vector(_It _F, _It _L, const _A& _Al)
: allocator(_Al), _First(0), _Last(0), _End(0)
{_Construct(_F, _L, _Iter_cat(_F)); }
template<class _It>
void _Construct(_It _F, _It _L, input_iterator_tag)
{insert(begin(), _F, _L); }
>>277 >_Iter_cat
糞MSが苦肉の策で作った代用関数。
理由と使用法はiterator_traitsのヘルプに記載。
原因がわかったので、なんとか修正してみました。
iterator insert(iterator _P, const _Ty& _X)
{size_type _O = _P - begin();
_Insert(_P, 1, _X);
return (begin() + _O); }
void insert(iterator _P, size_type _M, const _Ty& _X)
{_Insert(_P, _M, _X);}
void _Insert(iterator _P, size_type _M, const _Ty& _X)
{...
とinsert(_P, 1, _X)がiteratorによるinsertと解釈されないように、
呼び出されるべき2番目の処理を_Insertとして分けて、それを呼び出す
ようにしました。
(つづく)
因みにiteratorを使った_Insertとは、次のように引数の数が違うので
混同されません。
template<class _It>
void insert(iterator _P, _It _F, _It _L)
{_Insert(_P, _F, _L, _Iter_cat(_F)); }
template<class _It>
void _Insert(iterator _P, _It _F, _It _L, input_iterator_tag)
{size_type _O = _P - begin();
for (; _F != _L; ++F, ++_O)
insert(begin() + _O, *F); }
template<class _It>
void _Insert(iterator _P, _It _F, _It _L, bidirectional_iterator_tag)
{...
という事で、なんとか解決しました。
ありがとうございますた。
うーん。_Ucopyはそのままなので一抹の不安が残る。
ところで、この修正の意味ですが
insertをtemplate化する事により、
vector<int> v;
list<int> l;
で
v.insert(l.begin(), l.end())
と別の型のiteratorが使えるようになる!
という理解でよろしいのでしょうか?
× v.insert(l.begin(), l.end())
○ v.insert(v.begin(), l.begin(), l.end())
>>280 不十分だろ。
vector(size_type _Count, const _Ty& _Val)
を呼んでほしいところで
template<class _It>
vector(_It _F, _It _L)
がよばれてしまうんだから。
>> {_Construct(_F, _L, _Iter_cat(_F)); }
ここで、_F が整数型のときに、_Iter_cat(_F) が Int_iterator_tag のような
適切な型のオブジェクトを返し、
それに対して _Construct()が適切に多重定義されているなら別だが。
うーん。確かに。
とりあえず、コンストラクターに関しては引数二つ(allocator無しのとき)
は使用しなければ、回避でき?る?
vector(it1, it2)したいときには、insertを使えば。
と思ったら、insertも
void insert(iterator _P, size_type _M, const _Ty& _X)
void insert(iterator _P, _It _F, _It _L)
で同じ問題が起きるか。ぐげ。
size_type, const _Tyのコンストラクタとinsertは抹殺したくなった。
>>287 そうなんだ。結構根が深いんだよ、この問題は。
VC6SP5で俺がはまったときの解決策なんだが
まず次のような構造体テンプレートを作って
template<bool> struct Bool_type {};
typedef Bool_type<true> Is_integer;
typedef Bool_type<false> Is_not_integer;
template<class It>
struct Integer_traits
{ typedef Bool_type<std::numeric_limits<It>::is_integer> Integer_tag; };
たとえばvector の非公開メンバに次のような内部初期化メンバを加えて
vector::init_size(size_type, const T&)
{ /*...*/ }
template<class It>
vector::init_iter(It first, It last, Is_not_integer)
{ /*...*/ }
template<class It>
vector::init_iter(It first, It last, Is_integer)
{ init_size(first, last); }
(続く……)
コンストラクタをこんな感じにした
vector::vector(size_type s, const T& v) : /* 省略 */
{ init_size(s, v); }
template<class It>
vector::vector(It first, It last) : /* 略 */
{ init_iter(first, last, Integer_traits<It>::Integer_tag()); }
俺の場合はうまくいったんだが、まあ参考ということで
>>288 ディープですね。後でゆっくり参考にさせて頂きます。
一つ確認したいのですが、某サイトで次のような記述を見つけました。
This problem can occur whenever the code uses the two-argument constructor for vector<integer_type>
where integer_type is any integral type. This is a bug in the draft C++ standard, and the standards
committee is investigating solutions.
つまり、整数型を使用した場合に発生するバグ(仕様ミス)という事ですよね?
STLportでも、ちらっと見た限りは特に対応されおらず、同じ問題は起きると
思っています。何ちゃらEXTRA_TEMPLATE_CONSTRUCTORを使った場合ですが。
STLportよく見たら、同様の技を使ってますね。
>>291 VC6 のテンプレートは貧弱で、そうそう手が打てるわけでもないから
同じところに収斂するのも不思議ではないわな
コンストラクターに関しては、明示的に
vector<int> a((vector<int>::size_type)10, 10)
とすれば回避できるようです。
しかし、insertは回避できないようなので技を使うか、
insertの使用をあきらめるかしかないようですね。
VC7では解決してるのですよね?
294 :
デフォルトの名無しさん:02/09/20 20:21
>>293 解決してるよ
名前は多少違うが、
整数型タグとして Int_iterator_tag って空の構造体が定義してあって。
_Iter_cat() に整数型の引数を渡すとこれを返すように多重定義してある。
これを使って、
>>288の init_iter()のように _Construct() や _Insert() なんかを
多重定義してる。
勉強になりますた。ありがとさんでふ。
こういう有益なスレを見るとほっとするな。(関係無いのでさげ
まだBoost勉強中なんだが、
多倍長精度整数のテンプレってないん?
まだ詳しく見てないので見落としてるだけかも
しれんが...
多倍長クラスがテンプレである必要性が感じられないがどうよ
boostのSandBox覗くと確か big_int があるヨ。
つーかその手のものは、他の技術計算系のライブラリを当たって探すべきだと思うが。
std::list<boost::weak_ptr<int> > test;
が MinGW 2.0.0-3 と Boost 1.28.0 でコンパイルできません。
shared_ptr<int> なら通りました。
>>300 #include <boost/weak_ptr.hpp>
してないに50000ペリカ。
(なんでこういう輩はエラーの内容を書かないんだろう…。
自分がエラーメッセージ見て分からなくても他の皆は分かるだろうに…。)
303 :
デフォルトの名無しさん:02/09/21 14:40
__attribute__って何?
>>303 gcc 使い以外は知らなくて良い。gcc 使いは info 読みましょう。
305 :
デフォルトの名無しさん:02/09/21 17:21
おしえて厨でごめん
infoってなんですか。
(まじすいません)
>>306 そのリンクでinfoが何であるかわかるやつっているの?
infoっていんたーねっとのこと?
>>301 #include <boost/smart_ptr.hpp>
のままでした。
アホ でした。
逝って来ます。
>>302 エラーメッセージを張ったつもりになってました……
コピーしてちょっと他の事してたら、書き込むのを忘れてました。
ごめんなさい。やっぱり、逝って来ます。
>>302 >>310さんをいじめないで!
ヴァカにしているワケではないが、
たまには煽りに対して守ってみたくなった。
>>298 big_int<N>のような形であってもいいと思うんだが…。
>>299 boostライブラリgrepしてみたけどみつかりませんですた…。
勉強ついでに多倍長精度整数テンプレクラス。
作ってみてるよ。
今までどうやってやってるのかとても疑問だったんだが、
理論をみてみると恐ろしいほど単純だったんだね…。
目から鱗ですた。
>>312 <N>のNは何を入れればいいのでしょうか。桁数?桁数は可変長に
すればいいような気が。
314 :
デフォルトの名無しさん:02/09/22 01:32
>>314 boost::poolを使おうとするとDJGPPのm4が必要っぽい気がするが。
boost/pool/detail/pool_construct.batあたり見た感じ。
>>313 可変長も考えたが固定長にしてみた。
bitset<N>形式にするか、
vector<bool>形式にするかみたいな
感じかな。
STLとは話がずれてしまうのでsage
アセンブラなら簡単なんだが
>>317 わざわざサンクスです。
参考にさせていただきます。
>>318 ハァ?
簡単にキャリーが取れるとかそういうレベルか?
アセンブラで一からFFT実装したくないぞ
>簡単にキャリーが取れる
それめちゃめちゃ重要
>>322はアセンブラでは四則演算しかできないと思っているのか
そうでなくて、簡単にキャリーが取れることで、
他の実装面での面倒さに釣り合うの?
と言いたかった。
インラインアセンブラ・・・
>>324 何で実装しようと基本的な四則やビット演算を定義した後は
それを利用するから問題なくないか?
> 基本的な四則
を高速するのがアセンブラだと面倒という話ではないのか?
# 個人的には、FFTをCで書いてもAsmで書いても大して変わらんと思うけど。
えと、んと…お話中申し訳ないのですが…
ここはSTLスレッドです。
では、STLの質問を。
廚な質問だがスレ流れ引き戻しということでご容赦してほしい、、、
vector<vector< list<double>* > > link;
のような形で、list<double>へのポインタを保存したいのだが、
構造体Hogeへのポインタ
vector<vector<Hoge*> > link;
と同じような感覚で余分なオーバーヘッドかけずに使えるもの?
○?×?
#二重vectorのオーバーヘッドはもちろん覚悟
まだSTL使い慣れてないので、なんかコンテナへのポインタに抵抗が。
330 :
デフォルトの名無しさん:02/09/24 19:38
>329
○だろ
いちいち聞くな。
まあ、そう邪見にせんでも。
で、329 は、どの辺に不安をおぼえたんでしょうか。
operator->、operator*とかにじゃない?
>オーバーヘッド
コンストラクタに一票。
でもHogeのコンストラクタが明示
されていない諸刃の(略
大抵の計算はコンテナ内で完結できてしまうので、
コンテナにポインタをかける使い方、
list<double>* test;
とかは(あまり例題が見つからないせいもあり)使うのになんか不安を覚えました。
本当に(いちいちオブジェクトを作らずに)単なるポインタとして扱ってくれるか
確認がとりたかった次第です。
例えば、
list<list<list Hoge *> > > link;
とか連なってくると、なんかだんだん疑心暗鬼になってきました。
スマソ
さっそく付け忘れてるし、、 <>
すんません。
問題無し。
それより2重vectorはオーバーヘッドが出るだけでなく例外安全性を
損なうから避けた方がいい。
>>336 例えばどんなこと?
具体例を出していただけるとありがたい。
338 :
デフォルトの名無しさん:02/09/25 05:25
VC6のSP5で、#include <stream> すると次のエラーでコケるんですが、
似たような症状の方おりませんか? stlportを入れてますが、iostream
はVCのを使うようにしてます。
c:\program files\microsoft visual studio\vc98\include\fstream(217) :
error C2059: 構文エラー : '&'
c:\program files\microsoft visual studio\vc98\include\fstream(213):
クラス テンプレートのメンバ関数 'void __thiscall
std::basic_filebuf<char,struct std::char_traits<char> >::_Init(struct _iobuf *,
enum std::basic_filebuf<char,struct std::char_traits<char> >::_Initfl)' のコンパイル中
c:\program files\microsoft visual studio\vc98\include\fstream(218) :
error C2143: 構文エラー : ';' が '}' の前に必要です。
c:\program files\microsoft visual studio\vc98\include\fstream(213):
クラス テンプレートのメンバ関数 'void __thiscall std::basic_filebuf<char,struct std::char_traits<char> >::_Init(struct _iobuf *,
enum std::basic_filebuf<char,struct std::char_traits<char> >::_Initfl)' のコンパイル中
#このスレじゃまずいかな・・
339 :
デフォルトの名無しさん:02/09/25 05:26
>>338 #include <stream> は <fstream> の間違いです。
>>338 寝ぼけて.cppのど真ん中でincludeしてたせいですた。
なんでそれだとだめなのかわかんないけど。。。。
>>336 例えば、
vector<vector<int> > v;
v.push_back(vector(10, 3));
v.push_back(vector(20, 2));
v.push_back(vector(30, 4));
まで成功していたとして、
v.erase(v.begin());
とすると、内部では
v[0] = v[1];
v[1] = v[2];
v[2].~vector<int>();
--(vのサイズ);
という処理が行われる。
ここでもし2番目の代入演算子が例外を投げると、vectorの中身は
{{20, 20}, {20, 20}, {30, 30, 30, 30}}
という状態になってしまい、処理が失敗したのにvectorの中が変わる、
という状況が起こる。例外をキャッチしても、どこが書き変わったかは、
例外が起こった場所によって変わるから、結局例外が起こった場合
vectorの中身は全く信用できなくなる。ただ、vectorが壊れるわけでは
ないから、開放だけは安全に実行できる。
コピーコンストラクタ、代入演算子が例外を投げる場合は、コンテナに
入れるとどうしてもこの種の問題が起こるから、例外が起こったら
有無を言わさず開放してしまうか、あるいは例外を起こすオブジェクトを
コンテナに入れる時はshared_ptrにくるんでから入れるのが正解。
>>341 詳しい説明サンクスです。
>コピーコンストラクタ、代入演算子が例外を投げる場合は...
たしかPart1にも書いてあったやつですね。
確かにユーザクラスであれば考慮して例外をなくすこともできるが、
STLのであれば…どうしようもありませんね。
>shared_ptr
shared_ptrは上記の操作では例外を投げないことを保証
してるってことなのかな?
まだshared_ptrは見ていないので、後ほど参照してみまつ。
ありがとうございますた。
344 :
デフォルトの名無しさん:02/10/01 19:10
mapの質問です(環境はBCC5.5.1)
mapにmapを持たせて
↓
map< string, map< string, string > > inimap;
insertで値を代入したいんですが、
「含まれる方のmap」を先に作っておいて
↓
map< string, string > temp;
temp.insert(map< string, string >::value_type(key, value));
inimap.insert(map< string, map< string, string > >::value_type(section, temp));
↑
とやるしか方法は無いんでしょうか?
>map< string, string > temp;
の部分は、どうせ1要素しか必要無いんだからpair型(でしたっけ?)
かなんかで代用できるんじゃないのかーとか思ったんですが
イマイチ良くわかりません
ちなみにtempを作らないで1行で済まそうとしたらコンパイラに怒られました・・・
//直上でコンテナ内コンテナの危険性について触れていて
//本当にこんな事して良いのか不安ですけど・・・
>>344 単純にmapのコンストラクタを使えばいいんじゃない?
int main()
{
std::map<std::string, std::map<std::string, std::string > > inimap;
inimap.insert(std::make_pair("abc", std::map<std::string, std::string>()));
inimap["abc"].insert(std::make_pair("def", "ghi"));
std::cout << inimap["abc"]["def"] << std::endl;
}
一応念のため書いておきます。
(2)value_typeを使う。
inimap.insert(std::map<std::string, std::map<std::string, std::string> >::value_type("abc", std::map<std::string, std::string>()));
(3)pairを使う。
inimap.insert(std::pair<std::string, std::map<std::string, std::string> >("abc", std::map<std::string, std::string>()));
347 :
デフォルトの名無しさん:02/10/01 21:58
>345
その方法だと(345氏の例に倣えば)
inimap["abc"][] と inimap["abc"]["def"] の2つの要素ができちゃわないですか?
理想としては狙った1要素だけinsertしたいんですが
例えば
std::pair< std::map< std::string, std::string > > PairTemp("def", "ghi");
みたいな方法って無いんでしょうか
要は1要素しか扱わないのにわざわざ新しくmapを宣言するのが
もったいないというか、非効率なんじゃないかと思ったワケでして・・・
>>347 それなら単に
inimap["abc"]["def"] = "ghi";
とすればいいのでは。それから、inimap["abc"][]という空のmapと
inimap["abc"]["def"]という中身の入ったmapは同時には存在しない。
>348
なるほど・・・
[]演算子だと「該当するキーが見つからなくて新たに挿入する場合」に
余計に時間がかかってしまうからinsertの方が良いかと思ったんですけど
そもそもmap持ちmapとかやってるヤシが気にする事じゃないっすか・・・
>>349 実はinsertで何とかしようとして、いろいろやってみたんですが、
mapの中にmapがある場合、コンストラクタだけでは足りないようです。
insert関数が何かやっているようなのですが。
どなたかこのコードを通るようにして下さいませんか。
typedef std::map<std::string, std::string> MapStringString;
typedef std::map<std::string, MapStringString> MapStringMapStringString;
MapStringMapStringString inimap;
MapStringString i2;
i2.insert(MapStringString::value_type("def", "ghi"));
inimap.insert(MapStringMapStringString::value_type("abc", i2));
inimap.insert(MapStringMapStringString::value_type("abc", MapStringString("def", "ghi"))); //この行が通らない
std::cout << inimap["abc"]["def"] << std::endl;
すみません間違いました。
typedef std::map<std::string, std::string> MapStringString;
typedef std::map<std::string, MapStringString> MapStringMapStringString;
MapStringMapStringString inimap;
MapStringString i2;
i2.insert(MapStringString::value_type("def", "ghi"));
inimap.insert(MapStringMapStringString::value_type("abc", i2));
inimap.insert(MapStringMapStringString::value_type("abc", MapStringString::value_type("def", "ghi"))); //この行が通らない
std::cout << inimap["abc"]["def"] << std::endl;
>351
あ〜
>344で言った「1行にまとめるとコンパイルエラー」って
ソレの事です
なんで通らないんでしょうねぇ・・・
>>352 なるほど、ここまで考えられて行き詰まっておられたのですか。
自然な考えでは、MapStringStringのコンストラクタを渡せば認識
してくれるはずなんですが。insert()関数に問題がありそうです。
一つの可能性としては、value_typeはpairを返すのであって、map型の
一時変数を返すのではないということです。
それで、pairとmapがかみ合わず、エラーが出るのではないでしょうか。
ですから、何とかしてmap型の一時変数を生成すればコンパイルは
通るはずです。
いろいろ調べてみましたが、std::mapにはpairを引数に取るコンストラクタ
はないようなので、std::map型の一時変数を生成することはできないよう
です。うーむ残念。
356 :
デフォルトの名無しさん:02/10/02 14:11
STLPortで、アルゴリズムのremove()にstd::ネームスペースを付けると
エラーになってしまいます。
#include <algorithm>
#include <list>
#include <iterator>
std::list<int> coll;
std::remove(coll.begin(), coll.end(), std::ostream_iterator(std::cout, " ")); // エラー
なぜか、std::を付けると、remove(const char*)の方を呼び出そうとして
エラーになります。std::を取ると正常にコンパイルできます。多重解決が
うまくできてないように見えます。
STLPortではalgorithmで定義されているアルゴリズムは、std::をつけるとだめ
なのでしょうか?
356です。
ちなみにgcc3.2(MinGW)でコンパイルすると、std::removeとしても
正常にコンパイルできます(そうあって欲しいものです)。
普通にstd::removeで使えるが
>>358 いろいろやってみた所、とBorland-C++5.6内蔵のSTLPortでだけ
エラーになるようです。これはバグということになるでしょうね。
どうも使いづらいです。かと言ってこの記事をC Buider相談室
に書いても多分無視されるでしょうし・・・・
360 :
デフォルトの名無しさん:02/10/02 18:17
あらかじめ充分なサイズを確保しておいたstringのイテレータbegin()を
char*を引数にとり、そこへ結果を入れて返す関数に渡した場合
その結果は未定義のカタマリですか?
std::string buffer;
buffer.reserve(1024);
snprintf(buffer.begin(), 1024, "test", 0);
みたいな・・・
>>361 ( ゚∀゚)アヒャ!
いや、えーと、ダメならダメで他の手段は無いですか・・・
static_cast<char*>(&buffer[0])とか・・・
vector<char> chbuf(1024);
snprintf(&chbuf[0], 1024 ...
とか
えーと、実は344からの続きなんです
具体的にやりたいことは、iniファイルの内容を
std::map< std::string, std::map< std::string, std::string > >
に取り込むという作業でして、現在の実装が
/* もちろんおそろしくて実行していませんがコンパイルは通ります */
#define INIMAP std::map< std::string, std::map< std::string, std::string > >
#define STRMAP std::map< std::string, std::string >
std::string SectionTemp, EntryTemp;
SectionTemp.reserve(MAX_LINE_LENGTH);
EntryTemp.reserve(MAX_ENTRY_LENGTH);
// iniファイルに含まれるセクションを全て取り出す
GetPrivateProfileSectionNames(SectionTemp.begin(), MAX_LINE_LENGTH, FilePath.c_str());
// 全てのセクションに対して処理されるまで繰り返す
while (SectionTemp.length()) {
// 現在のセクションをIniMapに登録する
IniMap.insert(INIMAP::value_type(SectionTemp.c_str(), STRMAP()));
// 現在のセクションに含まれる全てのエントリを取り出す
GetPrivateProfileSection(SectionTemp.c_str(), EntryTemp.begin(), MAX_ENTRY_LENGTH, FilePath.c_str());
// 全てのエントリに対して処理されるまで繰り返す
while (EntryTemp.length()) {
// エントリを'='で分解してIniMapに登録する
IniMap[SectionTemp.c_str()].insert(STRMAP::value_type(EntryTemp.substr(0, EntryTemp.find('=', 0)), &EntryTemp[EntryTemp.find('=', 0)+1]));
// 処理の終わったエントリを削除する
EntryTemp.erase(0, EntryTemp.find('\0', 0));
}
// 処理の終わったセクションを削除する
SectionTemp.erase(0, SectionTemp.find('\0', 0));
}
といったところでして、vectorで実装するとエントリを分解するあたりが
非常にややこしい事になってしまうんです
範囲削除もなかなか一筋縄ではいかなかったので
できればstringで実装したいんです
どうにかならないでしょうか?
ごめんなさい
GetPrivateProfileSectionNamesの事書くの忘れてました
こいつは渡したバッファに
「セクション1\0セクション2\0セクション3\0セクション4\0\0」
みたいな感じでiniファイルにある全てのセクションを返してきます
GetPrivateProfileSectionのほうは
「キー1=値1\0キー2=値2\0キー3=値3\0\0」
といった感じです
>>366 ちょっとデータの構造が違いますがプログラムを作ってみました。
#include <iostream>
#include <fstream>
#include <string>
#include <map>
const char* FILENAME = "ODBCINST.INI";
typedef std::map<std::string, std::string> MSS;
typedef std::map<std::string, MSS> MSMSS;
int main()
{
MSMSS inimap;
MSS tmp;
std::string buf, seckey, value1, value2;
int state = 0;
std::ifstream ifs(FILENAME);
while (true) {
if (!getline(ifs, buf)) break;
if (buf.length() && buf[0] == '[') {
inimap.insert(std::make_pair(buf, MSS()));
seckey = buf;
} else if (buf.length() == 0)
continue;
else {
value1 = buf.substr(0, buf.find("="));
inimap[seckey][value1] = buf.substr(buf.find("=") + 1);;
}
}
MSMSS::const_iterator pos = inimap.begin();
for (; pos != inimap.end(); ++pos) {
std::cout << pos->first << std::endl;
MSS::const_iterator pos2 = pos->second.begin();
for (; pos2 != pos->second.end(); ++pos2)
std::cout << pos2->first << '=' << pos2->second << std::endl;
}
}
369 :
デフォルトの名無しさん:02/10/02 22:43
vector<int>を継承したクラスを作成して、そのクラスのコンストラクタの中で
自身にpush_backするのは安全でつか??
>>369 vectorを継承するということは、vectorを「実装手段とする」ということ?
もしそうだったら、包含を使った方がよいです。
もし public派生なら、vectorの反復子は派生したクラスを正しく指せる
ように実装すべきでしょう。
371 :
デフォルトの名無しさん:02/10/02 23:07
372 :
デフォルトの名無しさん:02/10/02 23:15
すんません、
「vectorの反復子は派生したクラスを正しく指せる ように実装すべきでしょう。」
の意味がわかんないです・・・
>>372 vectorから派生したコンテナクラスは、vectorの一種であるから、vectorの
反復子も派生したコンテナを指せないといけない。そうしないと、オブジェクト
指向の大前提が崩れてしまう。
例えばvectorから派生したクラス名をneo_vectorとすると、
neo_vector<int> p;
vector<int>::iterator pos = p.begin();
のような事ができなければならない。
うむむむ、しかしそうなると、vectorコンテナの全メンバ関数が仮想関数
として宣言されてないと都合が悪いことになるな・・・・
実際はどうなんでしょうか?識者の方でこの当たりの事を実験してみら
れた方はいらっしゃいません?
>>373 特に何も書かなくてもコンパイルできてしまうんですが、
これじゃまずいってことですよねえ?
#include <vector>
using namespace std;
template < typename T >
class neo_vector : public vector<T> {};
class neo_vector2 : public vector<int> {};
int main( void ) {
neo_vector<int> v;
vector<int>::iterator pos = v.begin();
neo_vector2 vv;
vector<int>::iterator pos2 = vv.begin();
}
public継承しているのは、単に各種メソッドを委譲するのが面倒なだけです。
包含しておいてconstな参照だけ露呈してしまってもいいんですけど。。
>367
えーと、最初は私もifstream使ってやってたんですけど
不正なエントリを弾いたり重複を無視したり
そういう細かい処理はAPIが提供してくれるからまかせてしまおうと
GetPrivateProfile〜を使った実装に変えたんです
今回の質問の大筋は、char*の配列の変わりになりうる
STL(あるいはC++標準)のコンテナが無いかという事でして・・・
できればstringのように、範囲削除とか部分参照が簡単にできないかなぁと
まぁそんなわけなのですが、どうにかならんもんでしょうか
よく考えてみると、反復子というのは、コンテナそのものを指すわけでは
なく、コンテナの中身を指すんですよね。
だから、こういう場合反復子がオブジェクト指向かどうかという問題は
ちょっと違うような気がしました。
むしろ、次のような場合に問題が起きないようにすべきかも。
neo_vector<int> p;
vector<int>* vp = &p;
( ´-`).。oO(
>>370はどの程度STLを使い込んでいるんだろう...
>>379 済みません、書けば書くほどボロが出てくるようなので今日はこの辺で
逃げます。(汗
すみません、ちょっと不安になってきたので質問を変えて
「データ\0データ\0データ\0\0」というchar配列(vector<char>でも)を
stringにまるまるコピーする事って可能ですか?
普通に=演算子とかassign()を使っても、最初の\0までしかコピーされないですよね?
std::copy(charvector.begin(), charvector.end()-1, targetstring);
みたいな事ってできますか?
やってみてlength()をしらべりゃええんちゃうん?
length()が返すのは最初の\0までの長さと思うのですが・・・
>384
違うんですか?
環境はBCCなんですが
( ´-`).。oO(
>>360はなんでとりあえずやってみないんだろう...
>>385 C++標準ライブラリより。
std::string s(5, '\0');
s.length() == 5
( ´-`).。oO(std::copyが0を特別扱いしてたら世の中大パニックだよな...
( ´-`).。oO(
>>360理論だとstringでUCSは扱えないんだな・・
>382,>386
いや、std::copy(charvector.begin(), charvector.end()-1, targetstring);
ってコンパイルできませんよ?
例えば上記のような処理ってできないんですか?っていう質問なんですが・・・
>384,>387
最後の\0までの長さなんですね・・・失礼しました
>388
誰もそんなこと言ってませんよ・・・
>>391 これを応用してやってみて下さい。
int main()
{
std::string str(100, '\0');
std::string dst;
std::copy(str.begin(), str.end(), std::back_inserter(dst));
std::cout << "dst length = " << dst.length() << std::endl;
}
'\0'hakannkeinai
( ´-`).。oO(
>>360はなんでcpp3rd位読まないんだろ…
( ´-`).。oO(おなかすいたなぁ。御天でラーメンでも食ってこようっと..
( ´-`).。oO(back_inserterで変なことを考えてる高校生は俺ぐらいだろうな…鬱…
( ´-`).。oO(
>>396 童貞なのかい....?
( ´-`).。oO(そういう
>>398は道程なのだろうか…
( ´-`).。oO(
>>398 彼女はいるけど…(以下略)…
( ´-`).。oO(っていうかなんでこんなにレスがあるのだろう…
( ´-`).。oO(ネタがないからか…
( ´-`).。oO(さすがに26ですから それなりにヌルヌポッっと....
( ´-`).。oO(
>>400 女なんてナス入れりゃヒーヒーいうんだよ....
(´-`).。o○(漏れとしてはこっちの顔の方が好きなんだけど…
(´-`).。o○(じゃぁ漏れもそうしよう...
(´-`).。o○(輪郭を半角にしてみるテスト…
(;´-`).。oO(デッカイ蛾が・・・なんて言えないよな)
(´-`).。o○(深夜に伸びる妙なスレだなぁ.....
(´-`).。o○(
>>400 一発やるためにつきあってはみたものの、正直かわいくないし、どうやり捨てるかを考えるだけでも面倒でもういいや、引き篭もりで。って感じなのかな.......
(´-`).。o○(みんなお盛んだわね.....
(´-`).。o○(俺の彼女はかわいいよ....顔で選んだしなあ.....でも性格も割といい.....子供できたらどうしよう(((( ;゚Д゚))))ガクガクブルブル
(´-`).。o○(ってかあまりレス伸びないから見てる人少ないと思ってたけど...
(´-`).。o○(結構深夜でも見てる人いたんだね...
(´-`).。o○(生はいかん、生はいかんぞう…
(´-`).。o○(セクシュアル・テクニーク・リテラシー 略してSTL ということなのかな…
(´-`).。o○(ここもageるとオセロ祭りのコピペ貼られるのかな…
(´-`).。o○(セクース話しかしてないのにな.....
416 :
デフォルトの名無しさん:02/10/03 03:14
●●●●●●●●「オセロさえ納期内に作れない=OO役立たず 」祭り●●●●●●●
/| | |_____ΦΦΦΦΦΦΦΦΦΦΦ||ΦΦΦ
| | | ̄ ̄ ̄ /| ||
| | | / /|TTTTTT TTTTTTTTTT||TTTTT
| /\ | /|/|/|^^^^^^ |三三| ^^^^^^^^^^^||^^^^^^^
| / / |// / /|
| / / |_|/|/|/|/|
| / / |文|/ // /
|/ /. _.| ̄|/|/|/ Λ_Λ
/|\/ / / |/ / (___)
/| / / /ヽ /〔 非OO 〕〕つ
| | ̄| | |ヽ/l `/二二ヽ
| | |/| |__|/ Λ_Λ / /(_)
| |/| |/ ( ´∀`) (_) Λ_Λ
| | |/ // / ^ ̄]゚ (` )
| |/ ゚/ ̄ ̄_ヽ ⊂〔〔 非OO 〕
(´-`).。o○(どうもありがとう…
>>416
ん〜??
ここまで必死になって飛ばしたい恥ずかしいレスはどれだ?
>388=>393あたりか?
(´-`).。o○(暇なだけじゃないかな…
>>418 いや、片っ端からageて回られているようです。
OO信者さんの巡回ではないでしょうか?
>>420 え、オセロの祭りやってんのは非OO信者じゃないの?
(´-`).。o○(皆書かないだけで結構起きてるのね.....
(´-`).。o○(デバッグがおわんないだけだよ… STLPortの馬鹿。
(´-`).。o○(体を壊さないようにね.....
(´-`).。o○(ちょっとホロっときた。どうもありがとう…
(´-`).。o○(pc3.2ch.netが重いでつ...
(@´-`).。o○(今日は平方根計算の章終えたよ、次は2次方程式だってさ...
(´-`).。o○(解の公式をSTL使って無名で書いてみよう...
(´-`).。o○(STLで書くぐらいだったらlispで書こうよ…
(´-`).。o○(どうせ教科書どおりに書いても遅いだろうし…
(´-`).。o○(…STLは怒涛のインライン展開で速度的には全く問題ないが…?)
(´-`).。o○(…std::sortに至ってはqsortより一桁速いし…)
(´-`).。o○(良スレだなぁ…
433 :
デフォルトの名無しさん:02/10/03 20:07
(´-`).。o○(
>>390 "最後の\0"までぇ? んなわきゃねえだろ!よく考えろ。
(´-`).。o○(とかマジレスしてみようかな...
(´-`).。o○(std::stringは'\0'関係ないよね。どんな文字でもバイナリでも入れられるよん。
ピンポンパンポン
いいかげん、普通の会話に汁うぅぅぅっっっ!!!!!
(´-`).。o○(とか言ってみようかな...
(´-`).。o○(
>>436 は昨日の道程君かな...
(´-`).。o○(2chもう飽きてきたのに見てしまうのはなんでだろう…
(´-`).。o○(そのうち面白いネタを書き込んでくれるヤシがいるという期待感からさ......
>>441 (´-`).。o○(ハイ。直交しています...
(´-`).。o○(ラチがあかないのでここで素朴な質問...
なんで引数に副作用をもたらすことができるる
for_eachってないの?
あると何かと便利だとおもうんだが…
boostにあったら...ごめんなさい。
>>443 (´-`).。o○( for_each って引数に副作用をもたらすことができるけど?
void add_1( int& n ) { n = n+1; }
for_each( c.begin(), c.end(), add_1 );
>>444 (´-`).。o○(確かSTLでは引数の変更は禁止しているはずだけど...
(´-`).。o○(あ、ここでの引数とは、ファンクタを除外した話しね...
>>444 (´-`).。o○(std::transformではダメなのか?
>>446 (´-`).。o○(確かtransformは出力先の変更を許しているだけで、
入力元の変更は許してないはず...
ってかVCだと平気で入力元の変更できちゃうね。
もしかして単に入力反復子を認めるために禁止しているだけで
あって、利用者が前方反復子の保証さえ持てば変更しても
構わないのかな?
(´-`).。o○(んなワケないか...
448 :
デフォルトの名無しさん:02/10/04 11:56
>390
end()-1ってのは意図した動作とは違うと思う。
なんでmapってoperator []で参照しただけで
なければ新しく作成しようとするんですか?
そういう仕様が選ばれた理由を知りたいんですが…
C++ 3rd見たらそのことについて書いてありました。
以下、引用の要約
for_each()アルゴリズムはシーケンス変更なしの
アルゴリズムに分類されているけど、それは明示的に
(必ずしも)変更されるわけではないかららしいです。
ってことで、シーケンスの変更は可能です。
またtransformについては分類上シーケンス変更アル
ゴリズムですが、こちらも同様入力シーケンスが変更
される可能性があるようです。
ってことでウソついちゃった♪
(>ν< )> テヘッ♪
>>451 map<int, std::string> m;
m[1] = "abc";
とすると、m[1]が存在しなくても、pair<int, std::string>(1, "abc");
を挿入してくれる。もし新しく作成してくれなかったら、空のm[1]
を作ってから代入しなければならなかったろう。
>>449 std::map<std::string, std::string> cont;
string str=cont["ne-yo!"];
こうした場合、どういった動作を望んでるの?
exception?
でも存在確認はfindでできるのでexceptionと
似た操作は行えるし...
(´-`).。o○(なんでbinderのoperator()引数はconst固定なんだろう...
(´-`).。oO(equation...)
459 :
デフォルトの名無しさん:02/10/05 07:50
class Foo { public: int getLength(void) const; }; があり、
std::vector< const Foo* > v; があるとき、v の内容を Foo::getLength()
の結果の順にstd::sortしたいんですが、単にsortするとポインタのアドレス
順になってしまいますよね…。
operator< を定義すればよいのでしょうか? ちょっと方法が思いつかないので
教えていただけませんか。比較のために
std::binary_function< const Foo*, const Foo*, bool>
を継承したclassを一つ作る?しかないですか???
>>459 boostを入れて、
#include <boost/compose.hpp>
std::sort( v.begin(), v.end(),
boost::compose_f_gx_hy( // or SGI-STL の std::compose2
std::less<int>(),
std::mem_fun(&Foo::getLength),
std::mem_fun(&Foo::getLength) ));
とか。
(´-`).。oO( でもbinary_function継承クラスを作った方がわかりやすいかも・・・
>>460 す、すごい。僕の脳では絶対におもいつきません…
やってみます。どうも。
>>460 神!最高!チンコ!
(-_-).。oO(って言ってもいいのかな)
(-_-).。oO(compose2だとうまくいかないな...
(´-`).。oO( BCCだとコンパイル通らんな・・・
463氏と同様でした。boost入れてみます。
VC6+STLPort と g++ 2.96/3.2 です。
466 :
デフォルトの名無しさん:02/10/05 11:29
VisualC++ 6(SP5)でSTLを使っています。
戻りがvoidなメンバ関数を std::mem_fun() すると、
error C2562 (voidが戻りの関数で値を返そうとした) と怒られ、
コンパイルできません。
これは確かVCの有名な不具合だったと思うのですが、うまい回避方法って
ないのでしょうか? いまは、仕方がないので関数の戻りを意味もなくbool
にしています。
なにか知恵をくださいませ。
467 :
デフォルトの名無しさん:02/10/05 18:04
stlport-4.5,boost-1.28をdebian(testing)に入れてg++-3.2から
使おうと思ったのですが、不可解なコンパイルエラーがたくさん出て
困っています。同様の環境で使われている人はいらっしゃいますか?
とくに/usr/include/boost/*/detail/*hppのファイルにおいて
たくさんのシンタックスエラーが発生します。
テストしてみたサンプルは以下のような簡単なものです。
$cat test1.cc
#include<boost/lambda/lambda.hpp>
int main(){
boost::function<int,int,int> f;
}
$g++-3.2 test1.cc -o test1 -lboost_thread \
-I/usr/include/g++-3/ -I/usr/include/stlport/
何か助言があれば教えてください
>>463 compose2はf(g(x))のような合成関数を導くアダプタのようですね。
>>466 boost::mem_fn。これ。
>>467 1.28だとgcc3.2リリースより前の版だから、知らないコンパイラだぞゴルァという
警告が大量に出るが、それではなくて他にもエラーが出るのか?
とりあえずlambdaを使いたいのかfunctionを使いたいのかthreadを使いたいのか
はっきりしてから、最初の一個のエラーメッセージくらい貼り付けれ。
つーか、STLと別にboostスレ建てた方がよいかもね...
>>469 g++-3.2から/usr/include/c++/3.2/
などという新しいディレクトリ下のファイルを使うことに
なっているみたいなのですが(/usr/include/g++-3は使わない)、
これはg++の環境の話なのでGCCスレにいってきます。
ちなみに3.2の/usr/include/c++/3.2/にはヘッダーファイルに
stlportの拡張も一部取り込まれているみたいなので、
467を以下のようにシンプルな感じにしたらコンパイルは通りました。
$cat test1.cc
//#include<boost/lambda/lambda.hpp>
#include<boost/function.hpp>
int main(){
boost::function<int,int,int> f;
}
$g++-3.2 test1.cc -o test1 -I/usr/include/c++/3.2/
gccはc++のABI変更もあったので早いところ3.0,3.1系は廃棄処分に
してほしいですね(/usr/include/g++-3は2.95系専用という位置付けで)。
gccに依存した配布系でそれら古いものが使われることもないだろうし。。。
ちなみにboostスレは欲しいですね。でもgenerative programming
スレもそろそろ新スレが必要な頃だし、いいタイトルを付けてそっちと
一緒にやっていくのもいいかもしれないです。
×(/usr/include/g++-3は使わない)
○(/usr/include/g++-3は使わなくてもよい)
う〜ん。
スレ立てた後に言うのもなんだが...
細分化されると見づらくなる…。
boostをインストールしてみたが、まだ標準STLもまともに使いこなせて
ない今現在、boostを入れる意味があるのか悩んでしまった。
標準STLの欠点をうまく補ってくれる点ではありがたいのだが。
お礼を書くのをすっかり忘れてました。ありがとうございましたー
>>469 VC6 SP5 + STLPort + Boost で幸せに動作中でございます。
477 :
デフォルトの名無しさん:02/10/06 22:54
質問です。
std::mapで、キーの方を変更するには、どのようにしたらよいでしょうか。
例えば、std::map<std::string, std::string> m; で、
m.insert(std::make_pair("abc", "def"));
std::map<std::string, std::string>::iterator pos = m.begin();
m->first = "ghi";
とするとエラーが出ます。firstはconstのようなのです。何かスマートな
方法があるのでしょうか。
あっすみません、pos->first = "ghi"; でした。
>>477 erase して insert し直す必要があります。
仮に、強引にエラーを回避してキーだけ書き換えれたとしても、そんなことしたらBツリーが壊れてしまうので、やっちゃだめです。
>>479 レスありがとうございます。やっぱりそうなのですか。
確かにキャストを使って無理矢理キーを書き換えたらできないことも
なさそうですが、キーがソート順でなくなってしまいますね。
どうもありがとうございました。
481 :
デフォルトの名無しさん:02/10/07 06:35
std::find_if の発展版みたいな感じで、
find_if して、見つかった要素に何らかの Func unaryfunc を適用するようなのって
ありませんかね?boostでもいいです。
find_if と transform かなにかを組み合わせて自分で書くしかないですか?
>>481 transformよりはfor_eachかも
(´-`).。o○(っていうかさ、
>>443からの議論とカブるね。結論はなんだったんだっけ..
(´-`).。o○(CommonLispばりに混沌としてきたな
boost::make_indirect_iterator って、
VC++ではつかえないとか、CVS版のboostにしか入ってないとか
ありますか? なんか
error C2039: 'make_indirect_iterator' : 'boost' のメンバではありません。
らしい。鬱。。
#ifndef BOOST_MSVC
template <class OuterIterator>
inline typename indirect_iterator_generator<OuterIterator>::type
make_indirect_iterator(OuterIterator base)
だってさーあははははははははははは(涙
いい加減VC++にはなんとかなってもらわないと迷惑だな。
他のコンパイラに問題が無いわけじゃないけど、なんで
一番潤ってる企業の出すコンパイラがヘボイわけ?
ユーザー数が多いからって開き直ってるとしか思えない。
>>487 ストレスで禿げるほど同意。
VC6にはSP6って出ないんですかねえ・・・・
namespace fugahoge {
template < typename InIter, typename UnPred, typename Func >
inline bool apply_one_if( InIter start, InIter end, UnPred pfn, Func unaryfunc ) {
InIter result = std::find_if( start, end, pfn );
if ( result == end ) {
return false;
}
unaryfunc( *(result) );
return true;
}
}
でOKでしょうか?
ところでVC++.NETはどうなの?
少しはましになってる?
少しなら。
すみません、不勉強で申し訳ありませんが、
std::list<something> any;
std::list<something>::const_iterator i = any.end();
--i; //ココ
って合法か教えていただけませんでしょうか?
普通はreverse_iterator使うけど、
any.size() > 0なら、合法じゃないか。
>>492 list<>::iteratorは双方向反復子だから、any.begin() != any.end();なら
--i は使用可能です。
すばやい対応、感謝します。
なぜクラッシュするのでしょうか?
template<typename T> struct Fn : public std::binary_function<std::auto_ptr<T>, std::auto_ptr<T>, bool> {
bool operator() (std::auto_ptr<T> f, std::auto_ptr<T> s) const {
return f->geti() < s->geti();
}
};
class For_auto {
int i;
public:
int geti() const { return i; }
For_auto(int j) : i(j) {}
};
int main()
{
std::auto_ptr<For_auto> a(new For_auto(1));
std::auto_ptr<For_auto> b(new For_auto(2));
std::cout << std::max(a, b, Fn<For_auto>())->geti() << std::endl;
}
Generic Programmingスレからの出張っすか(汗
漏れそっちの元質問者(汗
>>497 そうそう(汗。
どうもstd::auto_ptrは使ったことないもんで、多分関数オブジェクトを
呼び出す時、仮引数(のようなもの)に所有権が渡ってクラッシュする
らしいです。
しかも、関数オブジェクトは同名のオーバーロードをするとエラーになる
ことがわかって(汗^2 です。
>>498 constな参照で受けるっつーのはだめなの?
>>499 動いたーありがとうございます!!
でもどうしてconstな参照にするとクラッシュしなくなるのでしょうか?
std::auto_ptrの特殊性によるものでしょうか。
>>500 参照なら所有権が移らないから。
別にconstは無くてもいいんだけど、constなものは普通constにする。
>>502 なるほどまた一つ勉強になりました。
>>501 貼ります
template<typename T> struct Fn : public std::binary_function<const std::auto_ptr<T>&, const std::auto_ptr<T>&, bool> {
bool operator() (const std::auto_ptr<T>& f, const std::auto_ptr<T>& s) const {
return f->geti() < s->geti();
}
};
class For_auto {
int i;
public:
int geti() const { return i; }
For_auto(int j) : i(j) {}
};
int main()
{
std::auto_ptr<For_auto> a(new For_auto(1));
std::auto_ptr<For_auto> b(new For_auto(2));
std::cout << std::max(a, b, Fn<For_auto>())->geti() << std::endl;
}
使ったことないけど…(ってか、クセがあるので使いたくない)
コピーすると所有権が移るから今回のようなケースではconst
云々ではなく、参照にしないとだめ。
このクセがあるからコンテナには使えないと聞いた。
もうスマートポインタは boost でいいよ。
>>500 a と b の大小を比較するために
> bool operator() (std::auto_ptr<T> f, std::auto_ptr<T> s) const
が呼ばれるとき、a と b が引数の f と s にコピーされるでしょ。
auto_ptr をコピーすると、元の a と b は所有権を失って NULL になってしまうです。
関数から戻ってきたら、a も b も NULL になってるから、
> max(a, b, Fn<For_auto>())->geti()
最後に geti を呼んだときに落ちる。
>>504>>506 ありがとうございます。やっぱりそうですね。関数オブジェクトは普通の
関数とは違うのかと思っていましたが、同じように考えればいいのですね。
>>505 boostもインストールしたんですが、イマイチ使い方がわからない状態
なのです。参考書も売られていないし。まずはstd::auto_ptrを使って、
その利点と欠点を知り尽くした後にboostのスマートポインタを使って
みようかと。
shared_ptrとかweak_ptrとかいろいろ種類があるようですね。
>>507 >まずはstd::auto_ptrを使って、
>その利点と欠点を知り尽くした後に...
あんたさぁ…
あんた、漢だよ!
少しは見習いまふ…
>>508 ありがとうございます!!さっそく覗かせていただきます。
>>509 いやあ漢だなんて、買いかぶり過ぎっす。自分の性格的に、骨まで
しゃぶり尽くしたいという衝動がありまして。言語要素にも、存在意義
というものを一つ一つ見いだしたいのです。
namespace hogeratta {
template< typename T > struct identity : public std::unary_function< T, T > {
result_type operator() ( argument_type arg ) const {
return arg;
}
};
}
で、"implicit typename is deprecated" っておこられるんですが、これって
gcc 3.2 のバグですか?なんか間違ったことかいてますでしょうか。
>>511 result_typeとargument_typeの前にstd::を付ければ。
514 :
デフォルトの名無しさん:02/10/09 01:49
>>512 うひゃー。でもTを直接つかうなら継承しなくていいよなぁ・・・・・
この警告は勘弁してほしいです。
>>514 よくわからんが、ヘッダファイルの中で
typedef T result_type;
のようになっているからだろう。
typedef typename T result_type;
となっていれば警告が出なかったかもしれない。
>>512 些細なことだけど
typename std::unary_function< T, T >::result_type operator() ( typename std::unary_function< T, T >::argument_type arg );
やね。
なるほど・・
libstdc++なおしてくれーって感じっすか。
>>511 namespace hogeratta {
template <typename T>
struct identity : public std::unary_function<T, T> {
typename identity::result_type operator() (typename identity::argumet_type arg) const {
return arg;
}
};
}
で動くよ。やってみそ。
520 :
デフォルトの名無しさん:02/10/09 21:16
typedef std::map<std::string, std::string> STRMAP;
STRMAP mymap;
とした場合、mymap["test"]が存在するか不定として
mymap["test"].assign("any string");
と
if (mymap.count("test") == 0)
{
mymap.insert(STRMAP::value_type("test","any string"));
}
はどっちが高速であると予想されますか?
>>520 ・前者は デフォルトコンストラクタ + 代入 の2段階になる
・後者は コピーコンストラクタ一発で済むかもしれない、かわりに
二分木をたどる処理が2回必要になるかもしれない
っつーか実装/環境による。
522 :
デフォルトの名無しさん:02/10/09 21:50
>>521 insert()は定数時間が保証されるとか
operator[]()はキーが無い場合対数時間が要求されるとか
そういう単純な話ではないのですか?
そういう水準の比較で良けりゃ、
・insert() の保証は O( log n )。
・operator[] はキーがあろうがなかろうが保証は O( log n ) まで。
・count() も同じ O( log n )。
結局どっちも O( log n ) だから速度のオーダは変わらない。おしまい。
が、前者ならstringのデフォルトコンストラクタのオーバーヘッドが
かかる(これがmapの操作と比較してどの程度の重さかはわからない)し、
後者はconutとinsertの二回木を下る分遅いかもしれない。
が、同じキーに対する探索はキャッシュされる実装になってて
事実上一回で終わって後者でも速かったりするかもしれず…etc。
>>523 よくわかりましたありがとう
(自分の質問が頓珍漢であることが・・・)
>>520 高速性を求めるなら、これでどうかな・・・。
でも mymap["test"]="any string"; の方が読みやすくて良いと思うぞ。
string key("test");
STRMAP::iterator i = mymap.lower_bound(key);
if(i != mymap.end() && i->first == key){
i->second.assign("any string");
}else{
mymap.insert(i, STRMAP::value_type(key, "any string"));
}
>>520 そもそも、"test"が存在する場合は上書きするつもり?しないつもり?
しかもなぜただのmapでcount()を使う?
上書きするつもりとして、ノードの追加には成功したが、文字列の代入は
例外で失敗した場合に、mapの中身が変わってしまうのがいやなら、
>>525のコードで、代入に失敗したら単にmapを消してしまうつもりなら
mymap["test"]="any string";だろう。
527 :
デフォルトの名無しさん:02/10/10 01:09
std::sortしてからstd::uniqっていう処理は、1行で書けますか?
>>520は抜けがあります・・・
後者は
if (mymap.count("test") == 0)
{
mymap.insert(STRMAP::value_type("test","any string"));
}
else
{
mymap["test"].assign("any string");
}
のつもりです
というか、setとごっちゃに理解してたようであります・・・
std::sort(...);std::uniq(...);
530 :
デフォルトの名無しさん:02/10/10 01:24
つれないなぁ・・
ごめん。
でも意味がイマイチわからない…。
sort()、uniq()を一発でできるアルゴリズムが
用意されているかってこと?
533 :
デフォルトの名無しさん:02/10/10 01:51
>>531 ごく単純に
sort(from,to,fn);
uniq(from,to,fn);
と書くより効率の良い方法はあるかなぁとふと思いました。
抽象的すぎて答えようがないですかねえ・・・・・・
uniqueは順序付けられたシーケンスが前提(のはず)
ってことはsortは必須。
そういうもの。
ってか、
・順序付け
・ユニーク
ならmapかset使えば?
535 :
デフォルトの名無しさん:02/10/10 02:06
>>535 もっとも、ほとんどの処理系ではstd::vectorでstd::sort(); std::unique();と
やった方がずっと速いけどね。
string.compare()の返値が「合致しているならゼロ」に気付かず延々悩んでしまった・・・
良いプログラムは良いリファレンスから
>>537 std::strcmp()と同じような返り値だね。
539 :
デフォルトの名無しさん:02/10/11 05:51
"ファンクタ" == "関数オブジェクト" ですか?
542 :
デフォルトの名無しさん:02/10/12 10:46
traitsって何よ?
どなたかわかりやすく教えてください
trait (トゥレイテゥ)
【名】《【複】traits》
(1) (人・物の) 特性, 特質, 特色
提供:R○b○c○de(俺の)
544 :
デフォルトの名無しさん:02/10/12 11:04
Please fuck me.
Oh! ah! uuhn!
Yes come on!!come on!
Ahhha!
Thank you!! Fuck you!!!
>>542 日本語読みは「トレイツ」
「型特性の宣言」みたいなのが主な使われ方
(アロケータはまた余計に説明すんのめんどいから省くけど)
template <class charT, class traits>
basic_string<charT, traits>
というテンプレートがあったとして、
basic_string<char, char_type>と宣言されていたら、
「char型のbasic_stringを、char_type特性として使うぞ」みたいな意味
(もちろんchar_typeがどういう振る舞いなのかは別の場所に定義されているわけだが・・・)
ちなみにboostにはtype_traitsやcall_traitsなどというテンプレートがあって
type_traitsは、テンプレートが展開されるときに
「テンプレートパラメータは数値を扱う型であるか?」とか
「相互にコピー可能な型であるか?」などを調べるのに使う
call_traitsは、例えばテンプレート化された関数の引数を
「組込型ならコピー渡し、コピーにかかるコストが大きいと予想される型はコンスト参照渡しにする」
とかいう使い方をする
と、思う
覚えたばっかで間違ってるかもしれん
547 :
デフォルトの名無しさん:02/10/13 05:25
vectorをただの配列にコピーする、もっとも格好いい方法はどんなのですか?
なるほど。動くね。
int main()
{
std::vector<int> v;
int a[10];
for (int i = 0; i < 10; i++)
v.push_back(i);
std::copy(v.begin(), v.end(), a);
std::copy(a, a + 10, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
550 :
デフォルトの名無しさん:02/10/14 02:42
イテレータでコンテナの要素を列挙中にコンテナの要素を挿入したり削除したりは
できませんか?
for (map<int, string>::iterator i = hoge.begin(); i != hoge.end(); ++i) {
…
if (ほにゃらら)
hoge.erase((*i).first);
こんな感じのコードを書いたら無限ループになりますた。
VC++6
>>550 hoge.erase((i++)->first);
こっちの方がいい。
hoge.erase(i++);
iteratorでループまわす奴はDQN
for (map<int, string>::iterator i = hoge.begin(); i != hoge.end(); ) {
…
if (ほにゃらら)
hoge.erase(i++);
else
++i;
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>555 >>556 で、boost の lambda
しかしfor_eachの中ではwhile(first != last) func(*first++);等としているわけで・・・
簡単なループ処理をする度にいちいち関数オブジェクトなんて作ってられない。
ちがうんだよ、
トリッキーなコードを書いて自己満足するためなんだよ!!!
for_eachぐらいじゃそうとも言えないか…。。。
>>558 マジレスすると、そうとも限らないというのが定説。
もっと効率が良いかもしれない。Effective STL参照。
>>561 漏れも以前はそう思っていたが、boost::bindを使えばfor_eachの第3引数
が常に非常にシンプルに書けることに気づいてからはiteratorでループはやめた。
もっとシンプルになるかとおもってlambdaに手を出して
轟沈したのは内緒。
566 :
デフォルトの名無しさん:02/10/14 15:45
>>563 つい面倒になって匿名名前空間内にただの関数つくってそれのポインタを
渡してしまうと逆に遅くなる罠。自分のメンバ関数に渡すとか、
inner class つくってoperator()なら問題ないわけだが特に後者はタイプ
数多すぎ(w
567 :
デフォルトの名無しさん:02/10/15 22:35
std::listは両方向リストですが、子のノードは一つしか持てません。
子のノードを複数持たせるには、どのようなコンテナ構造にすればよい
でしょうか。
569 :
デフォルトの名無しさん:02/10/15 23:24
>>568 ありがとうございます。その場合、std::listのように、親のノードを辿ることは
可能でしょうか。
std::set自体は赤黒木のようなもので実現されているらしいので、回転操作
が伴うため、要素の挿入の度に親がしょっちゅう変わってしまうようなことは
ないでしょうか。
ごめん俺ものすごーく適当に書いたんだけど、実際やるなら
データメンバは下のような感じになるか
template<class T>
struct mlist {
T value;
mlist<T> *parent;
std::set<mlist<T>*> child;
};
親が変わるっていうのはどういうことか理解できなかった。
571 :
デフォルトの名無しさん:02/10/16 00:07
>>570 親が変わるというのは、二分木の構造が変化するということです。
しかしよく考えてみると、std::setは親とか子という概念は始めから
ないことに気づきました。
データメンバに親と子へのポインタを持たせるということには気が
つきませんでした。普通のCのように考えればいいのですね。
どうもありがとうございました。
はぁ?
見直してみると
>>570はコンテナのノードであってコンテナそのものでは
なかったな・・・。まぁいいか。
>>572 例えば親が変わる例として、
2
\
1
に3を挿入すると、
2
/
3
\
1
になったとします。この場合、1から見た親は、2から3に変わって
しまっています。こういう事を避けたいのです。
childがvalueの順になってくれません。何がいけないのでしょうか。
template <typename T>
struct mlist {
T value;
mlist<T>* parent;
std::set<mlist<T>*> child;
mlist(T i = 0) : value(i) {
parent = 0;
}
};
template <typename T>
bool operator<(const mlist<T>& m, const mlist<T>& n)
{
return m.value < n.value;
}
続きです
int main()
{
mlist<int> mm;
mm.parent = 0;
mm.value = 111;
mm.child.insert(new mlist<int>(3));
mm.child.insert(new mlist<int>(1));
std::set<mlist<int>*>::iterator pos = mm.child.begin();
while (pos != mm.child.end()) {
std::cout << (*pos)->value << ' ';
++pos;
}
}
すみません、自己解決しました。しかし、もっとスマートな方法はないでしょうか?
template <typename T>
class Sort;
template <typename T>
struct mlist {
T value;
mlist<T>* parent;
std::set<mlist<T>*, Sort<T> > child;
mlist(T i = 0) : value(i) {
parent = 0;
}
};
template <typename T>
struct Sort {
bool operator()(const mlist<T>* m, const mlist<T>* n) const {
return m->value < n->value;
}
};
>>575 setに入るのはアドレスで、デフォルト(setの第2テンプレート引数を省略)では
それをそのまま比較して順序づけするからかな?
ああ
>>578 やっぱりそうなのですね。bool operator< を作っていろいろやってみたの
ですが、引数がクラス変数でないとダメとかコンパイラに叱られて、いろ
いろと文献を見ていたら、関数オブジェクトなら比較関数として渡せるこ
とがわかりました。
うーん複雑だ。
581 :
デフォルトの名無しさん:02/10/16 04:24
mapのメンバ関数であるlower_bound()って
要素が見つからないと新しく作って返すんですか?
よく考えたらイテレータが返ってくるし、そうなんですか
純粋に要素があるかないか調べたい場合はcount(key)ですか?
find(key)では?
>>582 find()もイテレータが返ってきますが・・・
見つからない場合は何が返ってくるのでしょうか?
>>582 すいません
stl_tree.hを読んで謎が解けました
find()だとend()が返ってくるんですね
>>583 ちなみにVC++6.0のヘルプによるlower_bound()の解説。
>map::lower_bound
>
>iterator lower_bound(const Key& key);
>const_iterator lower_bound(const Key& key) const;
>このメンバ関数は、制御シーケンスの中で key_comp()(x. first, key)
>を偽とする最初の要素 x を指す反復子を返します。
>該当する要素が存在しない場合、この関数は end() を返します。
一度まともな解説書を通読することを*強く*勧める。
>>585 ところがBCC5.5.1標準ではend()が返ってこなかったのです
暇なときにもうちょっと奥まで見てみますが
stl_tree.hのclass __Rb_treeの実装で、find()では
return (見つかったか)?見つかったヤツのイテレータ:end();
となっていて、lower_bound()では
return 何かのイテレータ; //この先(前?)を見てないので不明
となっていました
質問でち (・∀・)
map<string, size_t> の内容を、size_t 降順 + 大文字小文字区別無し string 昇順で
ソートして標準出力にでも出力したいのですよ。
が、map<K, T> は sort() にかけることができず、map<K, T, Comp> でも T を使った
ソートはできないみたいです。
なので、一度 vector<map<string, size_t>::value_type> に放り込んでから、sort() を
かけようと思うたのです。
が、今度は pair<string, size_t> の operator= が定義されていないとかでコンパイル
通りませんぬ。
仕方ないので pair<> 互換で operator= と operator< をつけた構造体を vector<> に
詰めたら、それでやっと sort() がかけられたのです。
でも、もっと簡潔な方法無い? map<> か pair<> をソートする方法。
588 :
デフォルトの名無しさん:02/10/17 23:49
>>587 pair<string, size_t>をインサートする時にソートする関数オブジェクトを
定義してやれば済むんじゃないの?
>>588 vector<> にも map<> にも、insert() で関数オブジェクトが指定できそうな
場所が見当たらないんだけど・・・。
意味が違う?
方法に気付かない漏れがアフォなの?
>>589 ちょっとboost使わないとスマートにならないけど、こんな感じでどう?
#include <iostream>
#include <map>
#include <algorithm>
#include <boost/compose.hpp>
struct StrCmpi {
bool operator() (const std::string& s1, const std::string& s2) const {
return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(),
boost::compose_f_gx_hy(std::less<char>(), std::ptr_fun(std::toupper), std::ptr_fun(std::toupper)));
}
};
int main()
{
typedef std::map<std::string, size_t, StrCmpi> Ssize;
Ssize mp;
mp.insert(std::make_pair("test1", 123));
mp.insert(std::make_pair("Test2", 456));
Ssize::const_iterator pos;
for (pos = mp.begin(); pos != mp.end(); ++pos)
std::cout << "string = " << pos->first << ", size_t = " << pos->second << std::endl;
}
>>589 スマソ。降順でしたね。std::lessをstd::greaterにしてくださひ。
違うか。string昇順&&size_t降順ですか。ちょっと待ってて。
うーんだめだ。std::mapまたはstd::multimapは、挿入時にキーでソート
して挿入はできるけど、二番目の要素でソートして挿入はできない
ようだ。誰か助けて〜。
>>593 お手煩わせてスマソ。
元々 boost 知らない漏れが書いたのは↓こんなの。
using namespace std;
typedef map<string, size_t> map_type; typedef map_type::value_type pair_type;
struct sort_pair {
string first; size_t second;
sort_pair(const pair_type &NewValue) { this->first = NewValue.first; this->second = NewValue.second; }
operator=(const sort_pair &NewValue) { this->first = NewValue.first; this->second = NewValue.second; }
operator<(const sort_pair &CompValue) {
int Ret = (int)this->second - (int)CompValue.second;
if(Ret > 0) return true; if(Ret < 0) return false;
return stricmp(this->first.c_str(), CompValue.first.c_str()) < 0;
}
};
int main()
{
map_type Map; char Buf[256]; const int ItemNum = 10;
srand((unsigned)time(NULL));
for(int i = 0; i < ItemNum; i++) { sprintf(Buf, "Test%u", ItemNum - i); Map.insert(pair_type(string(Buf), rand() >> 13)); }
cout << "==== Before Sort ====" << endl; size_t Cnt = 0;
for(map_type::iterator itrMap = Map.begin(); itrMap != Map.end(); itrMap++)
cout << ++Cnt << ": " << itrMap->first << "(" << itrMap->second << ")" << endl;
vector<sort_pair> Vector;
for(itrMap = Map.begin(); itrMap != Map.end(); itrMap++)
Vector.push_back(*itrMap);
sort(Vector.begin(), Vector.end());
cout << "==== After Sort ====" << endl; Cnt = 0;
for(vector<sort_pair>::iterator itrV = Vector.begin(); itrV != Vector.end(); itrV++)
cout << ++Cnt << ": " << itrV->first << "(" << itrV->second << ")" << endl;
return 0;
}
>>594 boost知らなくても、boost::compose_f_gx_hyを分解して書けば書けるよ。
それと、std::mapよりstd::setにpairを挿入した方がこの場合はいいようなので
それで作ってみます。
>>594 struct Comp {
bool operator()(const pair_type& a,const pair_type& b) {
return /* 比較結果 */;
}
};
vector< pair<map_type::key_type, map_type::mapped_type> > v(Map.begin(),Map.end());
sort( v.begin(), v.end(), Comp() );
あるいは
set<pair_type, Comp> s(Map.begin(), Map.end());
でソート完了、で十分でないの?
…あのさぁ…
string+size_tでソートかけるなら
setでいいのでは?
>size_t 降順 + 大文字小文字区別無し string 昇順
このい見がイマイチ理解できないのだが…
size_t+string?
それとも、
size_tまたはstringどちらかで切り替えられるって意味?
かぶつた。(´д` ;;
これでどうでしょうか。
#include <iostream>
#include <set>
#include <iterator>
#include <cctype>
#include <boost/compose.hpp>
typedef std::pair<std::string, size_t> Ss;
struct Cmp {
bool operator() (Ss s1, Ss s2) const {
if (s1.second != s2.second)
return s1.second > s2.second; //降順
else
return std::lexicographical_compare(s1.first.begin(), s1.first.end(), s2.first.begin(), s2.first.end(),
boost::compose_f_gx_hy(std::less<char>(), std::ptr_fun(std::toupper), std::ptr_fun(std::toupper)));
}
};
int main()
{
std::multiset<Ss, Cmp> ss;
ss.insert(std::make_pair("test1", 123));
ss.insert(std::make_pair("Test2", 456));
ss.insert(std::make_pair("Test2", 123));
std::multiset<Ss>::const_iterator pos;
for (pos = ss.begin(); pos != ss.end(); ++pos)
std::cout << "string = " << pos->first << ", size_t = " << pos->second << std::endl;
}
>>596-597 そうしようとするとボロボロにエラーが出るのは、コンパイラが VC6 だからなの?
しかし、漏れのせいで pair<596, 597> が出来上ってしまったようだ・・・。
>>603 601です。
std::mapだと、挿入時にsecondの値でソートできないので都合悪いです。
std::setにstd::pairを挿入するのが一番すっきりするようです。
関数オブジェクトCmpをちょっと修正します。
struct Cmp {
bool operator() (const Ss& s1, const Ss& s2) const {
if (s1.second != s2.second)
return s1.second > s2.second; //降順
else
return std::lexicographical_compare(s1.first.begin(), s1.first.end(), s2.first.begin(), s2.first.end(),
boost::compose_f_gx_hy(std::less<char>(), std::ptr_fun(std::toupper), std::ptr_fun(std::toupper)));
}
};
boostを使わないCmpはこのように書きます。
class Cmp {
static bool compare(char c1, char c2) {
return std::toupper(c1) < std::toupper(c2);
}
public:
bool operator() (const Ss& s1, const Ss& s2) const {
if (s1.second != s2.second)
return s1.second > s2.second; //降順
else
return std::lexicographical_compare(s1.first.begin(), s1.first.end(), s2.first.begin(), s2.first.end(),
compare);
}
};
>>603 >出現した単語の集計。
そっか…。
insert後にsize_tの値が変化する
(集計が続行される)ならsetにも
問題が出てくるね…。
setで集計情報更新ごとにerase、
insertするか、
map<size_t, string>でstringソート時に
map<string, size_t>でソートするか、
って方法でいかが?
>map<size_t, string>でstringソート時に
>map<string, size_t>でソートするか、
ごめん。
ここらへんは
>>597のコンパイルエラー
size_tまたはstringと勘違い…
601です。
後から集計するなら、std::setでなくてstd::vectorにpairぶちこんどいて、
最後にCmpを渡してstd::sortするのが簡単だね。
多分std::mapを使ったのは、mp[word]++;のような書き方が便利だから
でしょう。
std::vectorを使ったら、std::findでキーを検索して、secondの値を++
するしかないでしょうね。
610 :
デフォルトの名無しさん:02/10/18 04:58
for_eachの第3引数に与える関数オブジェクトは、voidが戻り値でないと(規格上は)
まずいんでしょうか? 戻りがなんであれコンパイルは通りますけども。
どうなんでしょう?
>>602 > そうしようとするとボロボロにエラーが出るのは、コンパイラが VC6 だからなの?
うそーん。…と思ったら、確かにsetのコンストラクタが変だな、VC6。
修正。
#include <色々>
using namespace std;
typedef map<string, size_t> map_type;
typedef map_type::value_type pair_type;
struct Comp {
bool operator()(const pair_type& a,const pair_type& b) {
return b.second<a.second ||
!(a.second<b.second) && strcmpi(a.first.c_str(),b.first.c_str());
}};
int main() {
map_type Map;
char Buf[256]; const int ItemNum = 10; srand(time(0));
for(int c=10;c--;) { sprintf(Buf, "Test%d", c); Map.insert(pair_type(string(Buf), rand() >> 13)); }
cout << "==== Before Sort ====" << endl; size_t Cnt = 0;
for(map_type::iterator itrMap = Map.begin(); itrMap != Map.end(); itrMap++)
cout << ++Cnt << ": " << itrMap->first << "(" << itrMap->second << ")" << endl;
set<pair_type, Comp> s;
copy(Map.begin(), Map.end(), inserter(s,s.end()));
cout << "==== After Sort ====" << endl; Cnt = 0;
for(set<pair_type,Comp>::iterator i=s.begin(); i!=s.end(); ++i)
cout << ++Cnt << ": " << i->first << "(" << i->second << ")" << endl;
}
>>609 最初からvectorに突っ込むなら、Loki::AssocVector辺りが便利かと。
>>610 > 25.1.1 For each [lib.alg.foreach]
> ....
> Notes:
> If f returns a result, the result is ignored.
mapに突っ込んでいろいろ操作したあと、
vectorにcopyして、sortすればええやん。
>>605-606 なるほど、そう書くのか。
漏れは C 上がりなので、文字列操作となるとすぐ <cstring> に逃げてしまう。
>>611 ありがとう、それでまま OK のようだ。
>>605、612
漏れは boost とか Loki とか外部ライブラリを全然知らんのだけど、習得には
およそどれくらいかかる?
英語もダメだから、日本語ドキュメントがほとんど無いというのにもつい二の足を
踏んでしまう。
>>613 漏れも最初はそう思ったんだが、どうも pair<> を食ったコンテナは sort() で
コンパイルエラーになるのだ、pair<>::operator= が定義されてないとかで。
だからソートに対応した sort_pair を 594 みたいに書いたんだが、set や
multiset なら sort() が要らなそうだね。
結局は 603 の通り 「出現した単語の集計」 なのだが、集計は最初から set<>
を使うのは無理がありそうなので map<string, map<string, size_t>> でして、
終わったら set<string, set<string, size_t, comp1>, comp2> に放り込んで
ソートという事てでよろしいか。
617 :
デフォルトの名無しさん:02/10/18 15:50
>>616 pairを食わせたvectorでもちゃんとソートできるよ。
typedef std::pair<std::string, int> Si;
struct Cmp {
bool operator() (const Si& s1, const Si& s2) const {
return s1.first < s2.first;
}
};
int main()
{
std::vector<Si> sv;
char buf[128];
for (int i = 0; i < 10; i++) {
std::sprintf(buf, "%d", std::rand());
sv.push_back(std::make_pair(std::string(buf), i));
}
std::vector<Si>::const_iterator pos;
std::cout << "--- before sort ---" << std::endl;
for (pos = sv.begin(); pos != sv.end(); pos++)
std::cout << "pair(\"" << pos->first << "\", " << pos->second << ")" << std::endl;
std::sort(sv.begin(), sv.end(), Cmp());
std::cout << "--- after sort ---" << std::endl;
for (pos = sv.begin(); pos != sv.end(); pos++)
std::cout << "pair(\"" << pos->first << "\", " << pos->second << ")" << std::endl;
}
>>617 Σ(゚д゚lll) 確かにできるな・・・。
つーか、漏れも最初はそう書いたんだけど、何故かできなかったのよ。
元ソース残ってないから検証できない・・・。
ところで、struct Cmp は binary_function<> を継承しなくてもいいの?
よくある解説には、必ずそうしろと書いてあるんだけど・・・。
理念上の問題?
>>618 酸楠、読んでみる。
>>619 unary_functionやbinary_functionは、argument_typeとかresult_type
という型名を使いたい時に継承すればいいんじゃないかな。
これらの型名はファンクタ名で修飾しないとエラーになるコンパイラ
もあるので、結構使いづらいですよ。
621 :
デフォルトの名無しさん:02/10/18 23:33
MFCでSTL(stlport)使おうとしたら
fatal error C1083: インクルード ファイルがオープンできません。'../include/stddef.32771'
っていうエラーが出るんですが
こんなエラー出たことある人いますか?
どうも修正方法がわからなくて困ってます
>>619 出来ないのは、たぶん vector< map::value_type > とやったから。
value_type::first は const なので、当たり前だが
value_type::operator=() は使えなくて、結局コンテナの書き換えが必要な
sort() も使えないことになる。
>>605 LokiはModernC++Design(日本語訳あり)を一冊読み切れば
すぐ使えるようになると思う。で、この本を読み終わったならば、
ドキュメントなしでもboostとかが何をどうやっているのか
理解できるようになってるはずなので、そっちも
てきとーに使っていくこともできるかと。
623 :
デフォルトの名無しさん:02/10/19 03:01
( `Д) <コンテナは確かに便利だ。よく使う。いや、無いと困る。
/(ヘ つ )ヘ 加えて、単純なアルゴリズムも便利な物が多い。
しかし、関数オブジェクトの必要性がどうしても分からない。
ひとつの処理のために、クラス作ってoperator()定義したり、
boost使って技巧を極めるより、泥臭くてもforで回した方が
素直に書けると思うんだけど。
>>622 らじゃ。でも先立つものが 。(´д`;)
>>623 例えば漏れの提出した質問
>>587 への一連のレス。
map やら set やらの要素を好みの並び順にするためとか。
これは for で解決できる問題じゃない。
関数オブジェクトったって、operator() の引数と中身は普通の関数と一緒
だし、その外側を包む struct 定義の分で 2、3 行増えるだけだし。
面倒と言う程でもない。
関数ポインタが代用になりそうな気が一瞬するが、それが通用するのは
アルゴリズム等で、テンプレート引数には指定できない。
アルゴリズムでも、関数テンプレートは使えない。
逆に言うと、処理する型が決まっている場合は、アルゴリズムには関数
ポインタで充分な気もする。
レス忘れ。
>>622 > 出来ないのは、たぶん vector< map::value_type > とやったから。
確証はないが多分それだ、ありがとう。
今度から気をつける。
>>620 >unary_functionやbinary_functionは、argument_typeとかresult_type
>という型名を使いたい時に継承すればいいんじゃないかな。
bind1st/2ndとか否定回路とか使うならこれらの肩名がないとコンパイルできんすね
>>624 ( `Д) <レスさんくす。
/(ヘ つ )ヘ 587からのレスをへ〜と思いながら眺めてたんだけど、
確かに、こういう風にずばっと解決すると気持ちがいいな。
「これがSTLの威力か!」ってね。
小さい単純なプログラムでいろいろ試してる所なんだけど、
まず、自分で全部書こうと先に思ってしまう。
これはC++を初めてやったときに「こんなもんCで全部できる」と
考えたときに似てる。まだまだ勉強不足だな。
keyクラスを作成してmap
629 :
デフォルトの名無しさん:02/10/19 14:58
>逆に言うと、処理する型が決まっている場合は、アルゴリズムには関数
>ポインタで充分な気もする。
inline化されんので遅い
>>629 そうかそういう説があるな。確かにそうだ。
>>626 本当だ、std::unary_functionを継承しないファンクタを使うと、std::logical_not
などを渡すとコンパイルエラーになる。知らなかった。
>>623 確かにひとつの処理のために、クラス作るのは泥臭い。
しかし ptr_fun や mem_fun があるじゃないか。
関数作るのも泥臭いって?
ウムム…
633 :
デフォルトの名無しさん:02/10/19 19:47
for_each(c.begin(), c.end(), lambda(int a){ /* ... */ });
とか、したい。
635 :
デフォルトの名無しさん:02/10/19 20:40
>>635 へー、いろいろあんのね。…日本語のドキュがあればもっといいんだが。
boostのlambda面白そうだね。使ってみるか。
うわー、boost/lambda/lambda.hppをインクルードしたらエラーが26個も
出ました(泣。
Borland-C++5.6です。gccとかでないとだめなのですか?
>>637 いやーでも俺は使わないな。自分で専用のlambda preprocessorを
書くほうがマシ。
>>636 しらなかた
サンクスコ。
641 :
デフォルトの名無しさん:02/10/19 21:11
>>640 ぐはっ、左様ですか…。
lambda ppか…はー、lambdaが標準に追加されれば問題ないのになぁ。
>lambdaが標準に追加されれば問題ないのになぁ。
そうね。
boost::lambdaでいくら頑張っても、"C言語でもOOPは可能だもんね!"
と熱弁をふるう連中なんかと同類になるだけな気がする。
644 :
デフォルトの名無しさん:02/10/20 19:00
唐揚げ
645 :
デフォルトの名無しさん:02/10/23 01:59
何かネタくれ。
647 :
デフォルトの名無しさん:02/10/23 02:44
>>646 カラアゲうまうまはもう食ってしまったYO。
カップラーメンでも食うか。仕方ないし。
>>645 643の意見に煽りをいれてみた挙句にboost::lambdaのわかりやすい解説と活用法をこのスレに書き始める、なんてのはどうだ?
もちろん、それを漏れが見たいだけだが。
>>648 Borland-C++ではboost::lambdaはコンパイルできないんだよなー。
かなりがっくし来てる。
gcc3.2(cygwin or MinGW)を使うしかない。今のところ。
int main()
{
double d[] = {1.111, 2.222, 3.333};
std::vector<double> v(d, d + 3);
std::for_each(v.begin(), v.end(), std::cout << boost::lambda::_1 << ' ');
std::cout << std::endl;
}
とか。くだらんな。
boostスレは別にある罠・・・スマソ
652 :
デフォルトの名無しさん:02/10/23 15:44
std::vector<double> dv; があって、dvの各要素は重複した値を持たないものとしまっす。
あるdouble値 hoge がdvの 何番目 に格納されているかを知るにはどうしたらいいで
しょうか?iteratorでループまわすしかないですか?
#知りたいのは、「何番目」であって、格納されている要素を指すiteratorでは
#ないです
653 :
デフォルトの名無しさん:02/10/23 15:47
654 :
デフォルトの名無しさん:02/10/23 15:49
>>653 >find()は検索対象が見つかればその要素へのイテレータを返し,
>見つからなければend()を返す.
ですから、駄目なのでは?
>>652 iteratorをdistance()すればいいんじゃないか?
検索して得られたiteratorと、dv.begin()を引数にして
std::distanceでいけそうですね。お騒がせしました。
distance(), advance() は結構見落としがちだわな。
ランダムアクセス反復子は - 演算子使えるんじゃねーすか?
>>659 ほんとだ・・
ちょっとだけ利口になりました。
661 :
デフォルトの名無しさん:02/10/23 16:02
>>655 >>659 ふと湧いた疑問。演算結果を受け取る変数の型は、
std::vector<double>::difference_type と
std::vector<double>::const_iterator::difference_type の
どちらが適切?
>>661 意味的にはどちらも同義だと思う。
どちらでもイイ!のでは?
・std::vector<double>::difference_type
vectorで使われているイテレータの差を表現する型
・iterator::difference_type
イテレータの差を表現する型
663 :
デフォルトの名無しさん:02/10/23 20:35
じゃぁタイプ数が少ない前者にしときまつ。
664 :
デフォルトの名無しさん:02/10/23 21:34
(数値の)絶対値を求める、って皆さんどうしてます?
標準C++でもboost使ってでもなんでもいいんですが。
int なら abs()
double なら fabs()
class なら if(a < 0) a = -a;
666 :
デフォルトの名無しさん:02/10/23 21:40
>>665 それだとクラステンプレートの実装を書いているときにイマイチなわけですが・・
>>666 ならば
template<typename T> inline T generic_abs(const T& a) {
return a<T() ? -a : a;
}
inline float generic_abs(float a) { return fabs(a); }
inline double generic_abs(double a) { return fabs(a); }
inline int gene...(以下略)
とでもしておけばよいでのは?traits化した方がよいかもしれんが。
669 :
デフォルトの名無しさん:02/10/23 21:52
了解・・
>>668 すでにそんなことをしているライブラリはSTL/boostにはないって事ですよね。
>>669 つか std::abs じゃダメなの?
671 :
デフォルトの名無しさん:02/10/23 23:45
>>670 それってint型しか取れないんじゃなくって?
>>671 テンプレになってるから、何でもOKだよ
うへ、じゃぁそれでOKじゃん。
674 :
デフォルトの名無しさん:02/10/23 23:56
g++ 3.2 では以下のようになっていた。テンプレートじゃないみたいだが・・?
規格には何とかいてあるんでしょうかね
$ grep -r abs /usr/include/g++-3/*
/usr/include/g++-3/cmath:float fabs (float);
/usr/include/g++-3/cmath:inline float abs (float x) { return fabs (x); }
/usr/include/g++-3/cmath:inline double abs (double x) { return fabs (x); }
/usr/include/g++-3/cmath:long double fabs (long double);
/usr/include/g++-3/cmath:inline long double abs (long double x) { return fabs (x); }
/usr/include/g++-3/cstdlib:inline long abs(long x) { return labs (x); }
/usr/include/g++-3/cstdlib:inline long abs(long x) { return x >= 0 ? x : -x; }
675 :
デフォルトの名無しさん:02/10/23 23:57
アルゴリズムにメンバ関数を渡す方法を教えてください。
struct C
{
vector<int> v;
void f(int x) { std::cout<<x; }
void NG()
{
std::for_each( v.begin(), v.end(), &C::f );
}
void OK()
{
std::vector<int>::iterator it( v.begin() );
while( it != v.end() ) {
f( *it++ );
}
}
};
std::for_each( v.begin(), v.end(),
boost::bind( &C::f, this)
);
が、漏れは一番見やすいと思っているが。
std::だけで書くなら、
std::for_each( v.begin(), v.end(),
std::bind1st( std::mem_fun( &C::f ), this )
);
だっけ? いまからコンパイルしてみる。
確認しました。
std::abs はテンプレートではありません。
唯の関数オーバーロードのようです。
>>669 さん嘘教えてごめんなさい
>>677 問題なさそうだ。
メンバ関数ポインタを mem_fun すると、元の関数の引数に加えて、呼び出
し先のオブジェクトを引数に加えた関数オブジェクトが帰る、とでも考えてください。
>>675 さらにおせっかいを書くなら、その関数が2引数以上だと、
bind1st/2ndを何度も使わなければならず、著しく可読性が落ちるから、
そんなら割り切っていつでもboost::bindを使っらええやん、と思ってしまう。
(実行)速度面ではどうなんですかね。検討したことがない。
コンパイル速度は落ちます。>boost::bind
681 :
デフォルトの名無しさん:02/10/24 00:15
VC6だと677がコンパイルできないのは、VC6のバグね。7なら問題ない。
>>669 complex とか valarray の abs を考えりゃわかるけど、
もともとそんなにgenericに書けるたぐいの関数じゃないし。
674さん 丁寧なレスありがとうございます。
boost::bind というのは使ったことが無いのですが
調べてみます。
>>681 VC6 + STLPortなら行けるみたいです。
貴重な情報感謝します。
683の書き込みは675の間違いです。
boost::bind もVC6では通らないですね。
テンプレート固有の訳分からないエラーがいっぱい出てきます。
685 :
デフォルトの名無しさん:02/10/24 00:31
>>683 え、ほんとにコンパイルできました?
俺が勘違いしているのかなぁ。
実際に、手元の環境では
c:\program files\microsoft visual studio\vc98\include\stlport\stl\_function.h(139) : error C2562: '()' : 関数は 'void' 型として宣言されていますが、値を返しました。
と言われるのですが。
>>684 ん、逆にboost::bindなら通ると思うんだが....
std::for_each( v.begin(), v.end(), boost::bind( &C::f, this, _1 ) );
と思ったら、
>>676 はtypoあり。ごめんなさい。上が正しい。
>>685 実は &C::f というのは投稿用に考えたサンプルで、675の手元のコードでは、
呼ぶメソッドがvoidじゃないに1ペリカ。
>>680 >その関数が2引数以上だと、
>bind1st/2ndを何度も使わなければならず...
std::bind*は2引数以外のファンクタは受け取れなよ。
しかし、std::bind1st(std::mem_fun(&C::f), this) の this とは一体何を
さしているんでしょう?
C c;に対して適用する場合は
std::for_each(c.v.begin(), c.v.end(), std::mem_fun(&c.f));
ではどうしてだめなんでしょうか?
>>690 >&c.f
こういう記法はC++にゃありません、としか言えないような・・
692 :
デフォルトの名無しさん:02/10/24 01:53
>>690 "メンバ関数ポインタ" でgoogleすると良いと思うけど。
あと679。
>>691-692 ありがとうございます。結局次のように書くことで無事コンパイルを通りました。
std::for_each(c.v.begin(), c.v.end(), std::bind1st(std::mem_fun(&C::f), &c));
なんとも不格好なのですが、このように書くしかないのでしょうか?
もっとスマートに書けないものでしょうか。
694 :
デフォルトの名無しさん:02/10/24 02:13
>>693 C c; に対して外部からfor_eachするのね (サンプルのコードとはちょっと違うね)。
>なんとも不格好なのですが、このように書くしかないのでしょうか?
俺の理解する限りではそれしかないと思うけど。
std::mem_fun1_t<void, C, int> fn(&C::f);
std::for_each(c.v.begin(), c.v.end(), std::bind1st(fn, &c));
とか書いてもスマートではないよねえ・・
695 :
デフォルトの名無しさん:02/10/24 02:17
>>693 >結局次のように書くことで無事コンパイルを通りました。
それより、VC6のvoid問題をどう回避したのかおしえてくれよう。
www.issei.org/diary/d200112b.html にも載っている問題。
C::f() の戻り型はvoidなんでしょう?
>>694 そうです。C c; はthisを持っているから省略してもいいと思っていたら
だめで、やっぱり &c は省略できませんでした。
手持ちの参考書を片っ端から読んで見たのですが、それらしい例が
載ってないのです。mem_funは鬼門なのでしょうね。
>>695 すみません、BCC5.5.1デス・・・・
そろそろmem_funの不便さがわかってきたから、boostでもやって
みようかなあ。
>>696 なんだVCじゃないのかYO!!
ところで695のURIはとても勉強になると思うよ。
>>698 すみません。BCCもboost::lambdaがことごとく撃沈するという不具合が
ありますので必ずしもいいとは言えません。
早速URL見てみます。
>>697 boost::bindは、単体で使える。一緒に覚えないといけないのは boost::ref くらいか。
boost::mem_fnとか、boost::function はあとまわしにして大丈夫よ。
そんな俺はtupleおよびmplと格闘中・・
徹夜コーディングマンセー。。。。
>>701 ご苦労様です。体を壊さないでくださいね。風邪が流行ってますから。
なるほど、boostを使うとこのように書けるのか。
std::for_each(c.v.begin(), c.v.end(), boost::bind(&C::f, &c, _1));
>>703 yes.
bindは、第一引数に何を渡すかで、微妙に挙動を(使いやすく)変えてくれるのがいいところ。何を渡せるかはオフィシャルのドキュソメンツに詳しく書いてあるます。
うーん、boostはやっぱりかゆい所に手が届きますね。
といいつつ本家boostスレは全く無視しているのであった。ホホホ
再びネタ切れのヨカーン。燃料投下キボンヌ
boost を VC6-STLport でコンパイルしてたら 「コンパイラのヒープが足りない」
とか言って Stop しますた。
メイクファイルいぢって /Zm200 オプションつけて動かしたらコンパイル通ったけど、
これで OK なの?
boost スレに逝ってきます。
>>710 staticはthisポインタ持たないからだね。
質問です。
std::vector< std::string > を char** にキャストできますか?
方法がわからないので教えてください。
初心者ですみません。
&vs[0][0]
別のコンテナから char** を得る方法はありますか?
面倒くさいから無理って事で。
vector<char**>を使うとか。
std::string< std::string > で c_str() を使うって「あり」ですか?
これが ????\0????\0????\0 .... ????\0\0 を指してくれれば・・・
>>718 すみません、欲しいのは char*** ではなくて char** なのです。
vector< vector< char > > v;
&v[0][0];
>>721 "\0" は付いてきてくれますでしょうか?
c_str() を使おうかと思っておりまして・・・
>>712 vector<string>が
|s|t|r|i|n|g|1|\0|s|t|r|i|n|g|2|\0|s|t|r|i|n|g|3|\0|
とメモリにマッピングされる保証は「ゼロ」なので
別の方法を考えてください
string::c_str()が\0で終わる事は保証されます
std::basic_string< std::string > ですね。失礼。
???
>>712 >>719のメモリレイアウトにこだわるのであればvector<char>しか無い。
"abc\0def\0ghi\0\0"に対して
挿入・削除・追加・ソート・検索等をしたいのであれば
文字列→適当なコンテナ<string>してから処理して
文字列に戻すのが簡単かな。
>>725 その通り!但しstd::char_traits<std::string>を定義する必要がある。
…ってんなわけねぇだろ!
>>727 vector<string> とは別のコンテナを用意しろ、ということですか?
>>728 どういうことでしょう?
>>712 もしかして、利用したい変更不可能な関数の引数がchar**型なんだけど
自分の管轄内ではstringの配列として管理しておきたいので
どうやって渡せば良いのか?っつー質問か?
そうだとすればchar**型の変数に代入してから渡すしかないぞ
vector<string> dataならchar** tempとして
i = 0; it = data.begin();
while (it != data.end()) {
strcpy(temp[i][0], it->c_str());
i++; it++;
}
とか
>>712 いや、そもそも
>std::vector< std::string > を char** にキャストできますか?
C++のどのキャストでも出来ません。で終ってもいいんだけど
vector<string>をchar**にする目的は?
これがわからないとなんとも…
もしかしたら char** にする必要が無いかもしれないし、
vector<string>が間違いかもしれない。
もうちょっと状況を詳しく。
>731
キャストと言ってるくらいだから temp の領域はとってないんだろ。
char*[] と要素ごとの char[] をそれぞれ new する必要があると見た。
vector<string> からのキャストを受け付けて、内部表現が char** の
struct でも作れば new と delete は自動化できるか。
732 の指し先は 731 じゃなくて 730 だった。
>>730 >
>>712 > もしかして、利用したい変更不可能な関数の引数がchar**型なんだけど
> 自分の管轄内ではstringの配列として管理しておきたいので
> どうやって渡せば良いのか?っつー質問か?
その通りです。説明不足すみません。
> そうだとすればchar**型の変数に代入してから渡すしかないぞ
> vector<string> dataならchar** tempとして
> i = 0; it = data.begin();
> while (it != data.end()) {
> strcpy(temp[i][0], it->c_str());
> i++; it++;
> }
> とか
↑利用させていただくかもしれません。
どうもありがとうございます
736 :
デフォルトの名無しさん:02/10/26 06:05
>>735 おいおい、それ char** じゃないよ・・・。
>>735 おいおい、それ char** じゃないよ・・・。
| CToolBarCtrl::AddStrings
| ツール バー コントロールで利用できる文字列のリストに、
| 新しい文字列を追加します。
|
| int AddStrings(
| LPCTSTR lpszStrings
| );
|
| パラメータ
| lpszStrings
| ツール バーの文字列リストに追加される NULL で終わる文字列
| を 1 つ以上持つバッファのアドレス。
| 最後の文字列は、2 つの NULL 文字で終わります。
-- 中略 --
| // adds three strings with one call
| lpszStrings = "String 1\0String 2\0String 3\0";
struct ToMultiSZ
{
ToMultiSZ(vector<string> vs)
{
size_t i = 1;
vector<string>::iterator itr;
for(itr = vs.begin(); itr != vs.end(); itr++) i += itr->size() + 1;
sz = new char[i]; i = 0;
for(itr = vs.begin(); itr != vs.end(); itr++) i += sprintf(&sz[i], "%s", itr->c_str()) + 1;
sz[i] = '\0';
}
~ToMultiSZ() { delete[] sz; sz = NULL; }
operator char *() { return sz; }
private:
char *sz;
};
void PrintMultiSZ(char *sz)
{
if(!sz) return;
size_t i = 0;
while(sz[i]) i += fprintf(stdout, "%s\n", &sz[i]);
}
int main(void)
{
vector<string> vs;
vs.push_back("Test1"); vs.push_back("Test2"); vs.push_back("Test3"); vs.push_back("Test4");
PrintMultiSZ(ToMultiSZ(vs));
getchar();
return 0;
}
ついで: char* じゃなくて char** にするやつ (最初こっち作ったよ (涙))
struct ToCharPP
{
ToCharPP(vector<string> vs)
{
num = vs.size();
if(!num)
pp = NULL;
else
{
pp = new char *[num + 1];
size_t cnt = 0;
for(vector<string>::iterator i = vs.begin(); i != vs.end(); i++)
strcpy(pp[cnt++] = new char [i->size() + 1], i->c_str());
pp[num] = NULL;
}
}
~ToCharPP()
{
if(pp)
{
for(size_t cnt = 0; cnt < num; cnt++)
delete[] pp[cnt];
delete[] pp;
pp = NULL;
}
}
operator char **() { return pp; }
private:
char **pp; size_t num;
};
struct vs2sz
{
void operator()(const string& s)
{
if (m_bFirst)
m_bFirst = false;
else
m_v.pop_back();
copy(s.begin(), s.end(), back_inserter<vector<char> >(m_v));
m_v.push_back('\0');
m_v.push_back('\0');
}
vs2sz(vector<char>& v): m_v(v), m_bFirst(true)
{}
vector<char>& m_v;
bool m_bFirst;
};
void for()
{
……
vs // vector<string>
buf // vector<char>
buf.reserve(100);
……
for_each(vs.begin(), vs.end(), vs2sz(buf));
……
bar.AddString(&buf[0]);
}
vs.empty() == true の時 buf.empty() == true に注意。
>>737-738 どうもありがとう。
ToCharPP のようなラッパー構造体(クラス)とオペレータ char** を参考にさせていただきます。
>>739-740 どうもありがとう。
これは vector< string > ではなく vector<char> に "\0" を 加えているのですね。
疑問なのですが、
"abc\0def\0ghi\0\0"
疑問なのですが、
"abc\0def\0ghi\0\0"
↑ここの"\0\0"を付加しているようですが、
↑ここの"\0" は反映されますか?
>>736 > | パラメータ
> | lpszStrings
> | ツール バーの文字列リストに追加される NULL で終わる文字列
> | を 1 つ以上持つバッファのアドレス。
> | 最後の文字列は、2 つの NULL 文字で終わります。
型が LPCTSTR ですが、文字列が"\0"で区切られ最後に"\0\0"がつくので、
char** で考えてます。もしかしてまちがっていますか?
const の事でしたら、後でどうにかしますので問題ありません。
>>742 反映?何に?
あとWindowsSDKで\0区切りの文字列の
本当の終端が\0\0っていうのはお約束
>>743 >型が LPCTSTR ですが、文字列が"\0"で区切られ最後に"\0\0"がつくので、
>char** で考えてます。もしかしてまちがっていますか?
まったくもって間違っている
char**はchar型のポインタへのポインタ
今回扱っているのは\0区切りの文字列
>>743 に追記
> | // adds three strings with one call
> | lpszStrings = "String 1\0String 2\0String 3\0";
これには一番最後に見えない"\0"が付いているのではないのでしょうか?
それとも、単に、最後の"\0"の存在を明示的に表すため、
ここでは付けている?
私の考えは、
"String 1\0String 2\0String 3\0" のデータは
|S|t|r|i|n|g| |1|\0|S|t|r|i|n|g| |2|\0|S|t|r|i|n|g| |3|\0|\0| になっていて、
"String 1\0String 2\0String 3\0\0" のデータは
|S|t|r|i|n|g| |1|\0|S|t|r|i|n|g| |2|\0|S|t|r|i|n|g| |3|\0|\0|\0| になってしまう、です。
>>744 終端の\0\0の話ではなく、間の\0の話です。
vs2sz::operator()(const string& a) が、間の"\0"を反映しているのでしょうか?
>>745 char st[][]={ "AAA", "BBB", "CCC" };
は |A|A|A|\0|B|B|B|\0|C|C|C|\0|\0| になりませんか?
char st[][]={ "AAA", "BBB", "CCC" };
は
0:|A|A|A|\0
1:|B|B|B|\0
2:|C|C|C|\0
じゃなかったけ?
もまえらSTLの話をしる!
クソスレにすんなヴォケども。
>>746 見えない\0なんてあるわけないだろ?
勝手な妄想するなよ
>私の考えは、
だから、おまえの考えが間違ってるだけだって言ってるだろ?
>>747 反映しているっつー意味が全然わからんが
vector<char>に\0をpush_backすれば\0が挿入される
それと、2次元配列と\0区切りの文字は違うっつーの
>>749 ばらばらかどうかなんてのは問題じゃない
メモリイメージがどうであるかの問題
752 :
デフォルトの名無しさん:02/10/27 03:58
int hoge[] = { 2, 3, 7, 5, ....... }; という配列があって、この配列の初期化部分は仕様変更のたびに ころころ変わるので、要素数をかぞえたく(数えて何らかの変数にいれておきたく)ありません。
このようなhogeをvectorかsetにつっこみたいのですが、スマートな方法はどのようなものでしょうか?
hogeの最後の要素を特別な値(-1など)にすることは可能です。
vector foo(&hoge[0], &hoge[sizeof(hoge)/sizeof(int)]);
とかかな。
ところで、sizeof(hoge+int())はできるのに、sizeof(hoge/int())ができないのは何故なんだろう…。
754 :
デフォルトの名無しさん:02/10/27 04:23
>>753 あーーーーーーーー
その割り算のテクニック、知らぬ間に脳から蒸発していました。
感謝。どうもありがとう。
とおもったらコンパイルが通る(bcc&VC)だけで、
sizeof(hoge+int()) == 4になるみたい。謎だ。
756 :
デフォルトの名無しさん:02/10/27 04:37
とりあえずマクロ
#define ARRAY_SIZE(name,type) (sizeof(name)/sizeof(type))
にしておいたのですが、template使ってnameがポインタだった場合に
コンパイルエラーにすることはできないでしょうか?
ちょっとスレ違いで申し訳ないんですが。
>>755 g++ 3.2 でも4でした
757 :
デフォルトの名無しさん:02/10/27 04:51
template <class T>
inline size_t array_size(T* a){
if (sizeof(a) == sizeof(T*)){
// なんかエラー
}
return sizeof(a)/sizeof(T);
}
これはコンパイルエラーじゃないか。
>>755のヤツは
hogeがポインタに変換されてそれにint()が足されるから、つまりはポインタのサイズになるってことだな。
多分。
>>759 そんな使い方が出来るとは知らなかった…。。。
漏れも・・。早速手元の道具箱にpush_backしますた
762 :
デフォルトの名無しさん:02/10/27 05:19
ま た ビ ジ ュ ア ル シ ー か
あぁぁぁ〜〜〜本当だ〜〜〜〜(涙
Myクソsoftにテポドソ打ち込みたい気分。
>761
一番ケツにかい。
767 :
デフォルトの名無しさん:02/10/27 05:53
>>758 pointer型と同じサイズの配列を渡せなくないか・・・・?
s/サイズの/サイズの型の/;
>>758 char[256] を投げても 4 が帰ってくるし。
sizeof 使うならマクロじゃなきゃ駄目っしょ。
>>759 が通らないなら
>>756 しか無いんじゃないか。
#どうでもいいけど…
>>769 sizeof(array_name)/sizeof(array_name[0]) のほうが幾分マシですかね。
771 :
デフォルトの名無しさん:02/10/27 06:22
templateの特殊化でどうにかならんものでしょうか?
>>772 (略)言いたいだけちゃうんかと。(略)
と?
>>767-769 スマソ、寝ぼけてて頭が回ってなかったっぽい。
※頭が元々ダメとは言わないで…(w
>>771 「どうにかならんものでしょうか?」 という言いまわしが (・∀・)イイ!!
もうだめぽ
ビジュアルシープラァスプラァス(・A・)イクナイ!
VC版はー?
780 :
デフォルトの名無しさん:02/10/27 20:33
#define lengthof(x) lengthof_(x,sizeof(x))
template<class T> size_t lengthof_(T a[],size_t t)
{ return t/sizeof(T); }
じゃだめか?
>>780 それはポインタを渡しても通っちゃうし配列サイズにも使えないし。
782 :
デフォルトの名無しさん:02/10/28 04:28
VC6+STLPortで次のプログラムが
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
template<typename X> std::string int2string(X i) {
return "123"; // dummy
}
int main() {
std::vector<int> vi;
vi.push_back(1); vi.push_back(2); vi.push_back(3);
std::vector<std::string> vs;
std::transform( vi.begin(), vi.end(), std::back_inserter(vs), int2string<int> );
return 0;
}
error LNK2001: 外部シンボル ""class _STL::basic_string<char,struct
std::char_traits<char>,class _STL::allocator<char> > __cdecl
int2string(int)" (?int2string@@YA?AV?$basic_string@DU
?$char_traits@D@std@@V?$allocator@D@_STL@@@_STL@@H@Z)"
は未解決です
となってしまうのですが、なにか間違っているところがありますでしょうか?
教えてください。g++3.xだと通ります。
>>782 std::string (*pf)(int) = int2string<int>;
上の行をtransformの前に入れてみれ。
こける理由はよう分からん。どうも一度は明示的に実体を作ってやらないといけないのかな?
784 :
デフォルトの名無しさん:02/10/28 05:15
>>783 まだ試してないですけどナルホドという感じ。コンパイラの気分になってみればそんなもんかという気もするけど勘弁してほしいな。
普通にstructでoperator()にしますわ・・。どうも。
>>784 BCC5.6だと通るね。テンプレートの実体化のタイミングの問題のようだ。
786 :
デフォルトの名無しさん:02/10/29 19:22
C++の規格だとどちらの動作が正しいのですか?
>>786 間違ってる所なさそうだから通らないとおかしいのでは?
>>786 ってかリンク時の問題だから関係ないのでは。
そもそも外部参照になること自体がおかしいんだろ。
792 :
デフォルトの名無しさん:02/10/30 02:18
.obj にint2string<int>を含めなかったのはコンパイラが悪いわけで。
そういう意味で考えると、
VCは文法的に正しく解釈したので正常。
なので言語規格としては正しい。
ただしコードをはかない時点でVCコンパ
イラはアフォ。
ってことになるのかな?
>>794 どこらへんが?
むずかしいことばはわからない?
ひらがなでかいたほうがいいかな?
>>794 正直同感。ひらがなでもいいから、規格に沿って正確な技術用語で
言いたいことを書いてみてもらえない?
std::transform中に型特定して呼び出した時点でint2stringは実体化
しないとおかしいんじゃない?
>>782だが、Comeau C++でも何も警告されんね。ただしlinkできたかどうかは
online eva.ではわからん。残念。
Comeau C/C++ 4.3.0.1 (Aug 20 2002 15:39:28) for ONLINE_EVALUATION
Copyright 1988-2002 Comeau Computing. All rights reserved.
MODE:strict errors C++
In strict mode, with -tused, Compile succeeded (but remember, the Comeau online compiler does not link).
コンパイラは文法については正しく理解している。
ただコードを吐かないのは問題。
って意味なんだけど。
どう実体化すべきかまで含めて言語規格なんですが…
799がVCを擁護したくてたまらないのなら止めませんが。
>実体化すべきかまで含めて言語規格
そうなん?その部分を聞いているんだが。
> 799がVCを擁護したくて…
わかったわかった。
あんたが全て正しい!
>>799はVC厨!
これでいいか?
とりあえずマターリ進行なのに荒らすな。
ISO/IEC 14882読めば?
788=799は最初にname manglingの問題かなにかと取り違えたのが
残念だったということで。
803 :
デフォルトの名無しさん:02/10/30 03:21
次の話題に転換期待age
M$の言い分としては、
「呼ばれない限りコード生成は認めんぞゴルァ!
(ポインタ渡しは認めない)」
ってことではないかと。
漏れも同じエラーで引っかかったとき、そう解釈
してあきらめた。
とりあえずVC厨といわれそうなので…
M$、VCは糞!
とでも言ってみる。
>>803 あ、ゴメン…。
map<T,U>があるとき、格納されてるpairの型はmap<T,U>::value_typeっすが、
iteratorの型はmap<T,U>を使って表せますッけ?
うーん、map<T,U>::iterator::???
806 :
デフォルトの名無しさん:02/10/30 03:36
ごめん、完全に寝ぼけていた。撤回。
sleep(807);
...
Comeauって$50で全部(コンパイラ、標準ライブラリ、リンカ、デバッガ)ついてくるんですか?
そうなら買ってみてもイイ!かも
>>808 う〜ん...
スレの趣旨がずれてきているのでC++スレ
の方がよろしいかと。
ちなみに私は使ったことないのでナントモ。
スマソ...
810 :
デフォルトの名無しさん:02/10/30 06:05
multimapの重複したキーをスキップしながらfor_eachしてくれるような
アルゴリズムって標準では存在しないっすよね?
for_eachもどきの自作かboost::filter_iteratorでしょうか? なにか知恵を。
>>810 valuetypeの方はどういう基準で選別するの?
>812
見ないつもり
814 :
デフォルトの名無しさん:02/10/31 05:41
multimapをfindで検索するのとlower_boundで検索するのには、何か違いがあるのでしょうか?
一般的にどちらをつかうべきなのか悩んでいます。
find と lower_bound じゃ、ヒットする条件が違うだろ。
find だと指定した値ぴったしの要素じゃないと見つからない。
lower_bound は指定した値以上の要素があれば一致しなくてもヒットする。
自作の述語にnot2噛ましてsortに渡すとsegvる…
鬱死
partial_sort( be, en, en, not2(pr)) にしたら通った・・ナンデ。
いずれにせよ何らかのポしてんるだろ。
その述語晒せ。
820 :
デフォルトの名無しさん:02/10/31 11:36
>>819 struct CFooCompar : public std::binary_function< const CIFoo*, const CIFoo*, bool > {
result_type operator()( first_argument_type first, second_argument_type second ) const {
return ( first->GetSize()() < second->GetSize() );
}
};
です。ソートするvectorは、vector<CIFoo*>ではなくvector<CFoo*>で、
class CFoo : public CIFoo { ... }; です。
なんかマズイっすか? 環境はVC6+STLPortです。
GetSize()() は GetSize() だった・・コピペミス。
動くけどなあ・・・どっか間違ってる?
CIFoo と CFoo は適当に定義した。CFooCompar は 820 のまま。
class CIFoo {
protected:
int value;
public:
CIFoo() { value = 0; }
CIFoo(int i) { value = i; }
int GetSize() const { return value; }
};
class CFoo: public CIFoo {
public:
CFoo(int i) { value = i; }
};
ostream &operator<<(ostream &o, CFoo &c) { return o << c.GetSize(); }
int main()
{
CFoo c1(34), c2(78), c3(56), c4(12);
vector<CFoo*> vc; vector<CFoo*>::iterator itr;
vc.push_back(&c1); vc.push_back(&c2); vc.push_back(&c3); vc.push_back(&c4);
for(itr = vc.begin(); itr != vc.end(); itr++) cout << **itr << endl;
cout << endl;
sort(vc.begin(), vc.end(), not2(CFooCompar()));
for(itr = vc.begin(); itr != vc.end(); itr++) cout << **itr << endl;
cin.get();
return 0;
}
>>823 どうも。
こちらの手元でも単体では動きました。CIFooは純粋仮想関数
だけしかもっていなくてGetSize()はCFooの方でインプリされてるん
ですけどまぁ一緒ですよね。
というわけでSTLとは関係ない場所でメモリ破壊でもしてるかな・・
お騒がせしました。
class CIFoo {
public:
virtual int GetSize() const = 0;
};
class CFoo: public CIFoo {
int value;
public:
CFoo(int i) { value = i; }
int GetSize() const { return value; }
};
に直したけど、やっぱり動くね。何がいけないんでしょ。
>>825 CFooのGetSizeをvirtualに。また、両方のクラスに仮想デストラクタをつけましょう。
らじゃ。
式テンプレートって何?
template<typename T>
struct DeleteObject {
void operator() (T* ptr) {
delete ptr;
ptr = NULL; } };
class Test {
public:
vector<int*> v;
public:
Test() {
v.reserve(10);
for (int i = 0; i < 10; ++i) {v.push_back(new int);}
}
void Delete() {for_each(v.begin(), v.end(), DeleteObject<int>());}
~Test() { } };
int main() {
Test hoge;
hoge.Delete();
vector<int*> v(10);
for (int i = 0; i < 10; ++i) { v.push_back(new int); }
for_each(v.begin(), v.end(), DeleteObject<int>());
if (hoge.v[0] == NULL) { cout << "OK" << endl; }
if (v[0] == NULL) { cout << "OK" << endl; }
return 0; }
のソースの処理結果が
OK(main内部で回した奴)
しか表示されません。何故、Testで回したループは正常に動作しないのでしょうか。
>>829 正常に動作してるよ。
vector<int*> v(10); ←となっているから、main()内のvは実際には
20個まで増える。だからhogeとvは対称には比べられないよ。
なおかつ、operator()でポインタの値を書き換えたいので、
ポインタへの参照を渡さないといけない。
template <typename T>
struct DeleteObject {
void operator() (T*& ptr) {
delete ptr;
ptr = 0;
}
};
これで正常に動くと思うがどうよ。
template <typename T>
struct DeleteObject {
void operator() (T*& ptr) {
delete ptr;
ptr = 0; }};
class Test {
public:
std::vector<int*> v;
Test() {
v.reserve(10);
for (int i = 0; i < 10; ++i)
v.push_back(new int); }
~Test() { }
void Delete() {
std::for_each(v.begin(), v.end(), DeleteObject<int>()); } };
int main()
{
Test hoge;
hoge.Delete();
std::vector<int*> v;
for (int i = 0; i < 10; ++i)
v.push_back(new int);
std::for_each(v.begin(), v.end(), DeleteObject<int>());
if (hoge.v[0] == 0) { std::cout << "OK" << std::endl; }
if (v[0] == 0) { std::cout << "OK" << std::endl; }
}
>>829 mainのvで10個確保したのに、そこからpush_back?
スマソ。
>>830は無視してください。v.reserve(10)と書いてあった。鬱だ・・・・
取り敢えず
>>829がうまく動かなかったのは、ポインタの値を書き換えたい
のにポインタの参照を渡してなかったという事でよろしいか?
あ、違う。忘れてくれ。
833=836=漏れ。スレ汚してスマソ。
みなさんレスありがとうございます。
>T*&
ということは、ポインタ値を値渡ししているという認識で
あっていますでしょうか。
>833
ポカしてますね(汗
v(10, new int)でpush_backはなしの方向で・・・
>>838 ポインタの参照渡しです。
それから今実験してみたけど、v.reserve(10); としても空のvectorが
10個確保されるわけではないようだ。だからやっぱりhogeは10個まで、
vは20個まで増えることがわかったよ。
>>838 v(10, new int)だと、同じポインタが10個満たされるよ。
あいかわらずmultimapで悩んでいます。multimapに互いに異なるキーが何個あるか調べるのは、
iteratorまわしてiter->firstを set<key_type> につっこんでみるとか、
std::unique_copy あたりで vector<value_type> につっこんでみるとか、
そんな方法しかないでしょうか? コピーが発生しない上手な方法があったら教えてもらえませんか。
>>841 multimap::size_type count_unique( const multimap& x )
{
multimap::size_type result = 0;
const multimap::const_iterator end = x.end();
for( multimap::const_iterator i = x.begin()
; i != end
; i = x.upper_bound( i->first ) )
{
++result;
}
return result;
}
>>842 ありがとうございます。勉強になりました。
;; multimap::size_type って可能なんですね・・
;; multimap<hoge>::size_type しか許可されないかと思ってた。
>ポインタの参照渡しです。
T*&はそうですよね(汗
T*はポインタの値渡しだなぁと思いまして
>v.reserve(10); としても空のvectorが10個確保されるわけではないようだ。
>v(10, new int)だと、同じポインタが10個満たされるよ。
やっぱり、適当に書いてたらダメですね(汁
今度からは、ちゃんと考えてかきます(´-`)
>>843 型指定しないとコンパイルエラーになります。それで、templateを使って
型を類推させるようにしてみました。typedefが半分ほどしか活かされて
ないのが残念ですが。
template <typename Key, typename Value>
std::multimap<Key, Value>::size_type count_unique(const std::multimap<Key, Value>& x)
{
typedef std::multimap<Key, Value> Mkv;
Mkv::size_type result = 0;
const Mkv::const_iterator end = x.end();
for(Mkv::const_iterator i = x.begin(); i != end; i = x.upper_bound(i->first))
++result;
return result;
}
>>845 そうですね。T*はポインタの値渡しですね。だから、ポインタの指す値
を変えることはできても、ポインタそのものの値の変更は反映されな
いのでしょう。
ところで、C++標準ライブラリP236のmultimapメンバ関数upper_boundの
説明はどうも誤訳のようですね。「戻り値はvalue以上の」とありますが、
これは「戻り値はvalueより大きい」となると思います。
>>849 それとも、原文からして間違っているのかなあ?一応鉛筆で直して
おいたけど。英語の原本は持ってないのです。
851 :
デフォルトの名無しさん:02/11/02 16:52
vectorに何かをcopyするときって
vector v;
copy(hoge.begin(), hoge.end(), back_inserter(v));
でできますが、vがsetの場合ってcopyの第3引数はどう書けば
よいのでしょうか? 教えてください。
set<foo> s;
copy(hoge.begin(), hoge.end(), inserter(s, s.end()));
853 :
デフォルトの名無しさん:02/11/02 17:13
ありがとうござました
back_inserterってやっぱいつ見てもいやらしいなあ
何を考えている
*foo.end() みたいにend()の先を参照するのは安全でしょうか。
普通こんなことしないと思うけど、なんとなく気になったんで。
ただのゴミだと思うけど、SEGV出る可能性あるのかな。
>>857 Cで言うと配列の添え字の一つ大きい値を実体化させるようなもので、
危険です。
>>857 *foo.end() が既にダメだから、「end() の先」 じゃなくて 「end() 以降」 は
アクセスしない事。
「ただのゴミだと思う」 って、アクセスしちゃったの? 知らないよ。
仮に foo.end() にアクセス成功したとしても、*foo.end() が何を指すかわから
ないでしょーが。
iterator::operator* がガードしてくれる場合もあるかもしれないけど。
何かアクセスしたい事情でもあるの?
>>858 未確認情報だけど、T array[N]; の場合、array[N] にアクセスできる保証がある
って聞いた事がある気がする。
あくまで未確認。
858です。
>>859 そうです。ANSI-Cではarray[N]のアドレスを取れることを保証しています。
但し値を実体化したら動作は未定義です。
STLのend()もこれと事情は似ていて、end()は取れますが、*end()は未定義
です。
>>860 array[N]のアドレスを取れるだけで、アクセスできる保証があるというのは間違い?
先、って言うのは*適用した先、って意味です。
全くもってアクセスしたい事情はないんですが、
厳密に駄目なのか、ひょっとしたらendだけなんか保証があるのかとか
はっきりわからなかったってことです。
end()と比較したり、end()のイテレータを取ることは許されていますが、
*end()は何もないので、動作は未定義です。
>>861 array[N]はアドレスを取ったり、アドレスと比較したりする事だけが許されて
いて、アクセスした時の動作は未定義です(大抵他の確保したオブジェクト
を指すことが多い)。
>>861 俺もどっかでそんな話聞いた気がする。
アクセスしても意味のある値は取れないけどSEGVとかにはならないとか何とか。
気のせいだったかしら?
でもさ、array[N]と*(array+N)は等価だから、*(array+N)って明らかに存在
しないから、array[N]にアクセスするのもやっぱりまずいでしょ。
>>863 そか。サンクス。
>>865 そうだよね。
もちろん漏れはそれを当てこんだプログラミングなんかしない。
867 :
デフォルトの名無しさん:02/11/05 16:15
STLにとって難しい場合、それは最初に考慮されるかもしれませんが、
他方では、それ、彼は自然、およびそれを使用する方法へのその構造
(回使[[ものいくらか]])を理解することができます?p、達する、そしての外部で。
>>867 あなたの文章を理解するのは難しいです。
869 :
アバウト意訳:02/11/05 16:50
あなたはSTLが難しいかもしれないと思うかもしれません。
しかし、それが使用法として構造上自然であると、
いくらか学習することで理解できるようになるでしょう。
>>869 すげー。
でも 「p、達する、そしての外部で。」 は?
あ り が と う 。
874 :
デフォルトの名無しさん:02/11/05 21:30
それが非常に困ったから、私はSTLを研究したんですが、
それは熟練するために全能力に置いて心細いです。
それはどんなに問ったんですか。
>>874 1 行目と 2 行目は理解できるけど、3 行目は理解できない。
>>875 「どんな風に練習されたんですか?」のような気がする。
877 :
デフォルトの名無しさん:02/11/05 21:50
国語のスレはここですか
878 :
デフォルトの名無しさん:02/11/05 22:01
std::copy()とstd::copy_backward()の使い分けはどのようにすれば
よいのでしょうか?
>>878 コンテナに要素が転送される順番が重要な時は、copy() と copy_backward() を
使い分ければいいんじゃないでしょうか。
例えば、コピー先が要素のキー値の重複を許していない場合とか・・・。
あんまり思いつきませんけど。
普段は copy() 一本でいいんじゃないでしょうか。
いきなり copy_backward() とか書かれると、意味を探らないと逝けなくなるし。
>>878 >>879さんの意見の他に、自分自身のコンテナ内でブロック転送する
場合、転送前後の領域が重なる際に使い分けが必要となる。
|a|b|c|d|e|
↓
|a|b|c|d|e|
のような時はstd::copy()でいいが、
|a|b|c|d|e|
↓
|a|b|c|d|e|
の時はstd::copy_backward()を使わないと内容が転送中に壊れてしまう。
>>879>>880 おおっありがとう!
どうやらCで言う所のmemcpy()とmemmove()のような関係にある
ようですね。ちょっとニュアンスが違うけど。
試してみます。
882 :
デフォルトの名無しさん:02/11/06 17:36
std::vector<var*>というコンテナに対して、iterator(に相当するもの)の値参照の返り値をvar*、
const_iterator(に相当するもの)の値参照の返り値をconst var*にしたいのですが
何かお約束の方法などないでしょうか。
# std::vector<var>とすればconst_iterator::operator*()の返り値がconst varとなって
# varをconstにしたいという目的は達せられるんですが、
# どうしてもstd::vector<var*>とする必要があるのです。
試してみたのは
1. std::vector<const var*>::const_iteratorを使う。
これだとstd::vector<var*>::iteratorからの代入が出来なくなってしまいます。
# gcc2.95ではiteratorはpointerと同義のようで出来るようですがgcc3.2では×です。
2. const_iteratorのoperator*()をオーバーロードする。
class my_const_iterator : public std::vector<var*>::const_iterator {
const var* operator*(void) { return operator*(); }
};
のようにconst_iteratorを継承してoperator*()をオーバーロードすると
(現在はとりあえずこうしています)、gcc2.95ではconst_iteratorはクラスではないから
継承できない(iterator≡pointer)とダメだしされます。
883 :
デフォルトの名無しさん:02/11/06 17:47
>>882 const var* foo = *citer;
ではあかんのけ?
>>883 それは逐次一次変数に代入してから使うということでしょうか。
できればconst_iterator::operator*()が直接const値になっていて欲しいです。
>>884 ちょっと眺めてみます。情報どうもです。
>>885 完成したら const_const_iterator とでも銘々して僕にもくださいw
とりあえず↓みたいな感じで私の欲しいものは得られそうです。
まだよく判ってませんがとりあえず使いながら理解していこうと思います。
--------------
#include <boost/iterator_adaptors.hpp>
typedef boost::indirect_iterator_pair_generator<
std::vector<var*>::iterator, // 元になるイテレータ(or ポインタ)
var // operator*(operator*())が返す修飾なしの型
// ここにconstと非constについての参照型やポインタ型が並ぶが省略可
> iterator_gen; // とりあえず命名
std::vector<var*> var_list;
iterator_gen::iterator i(var_list.begin());
iterator_gen::const_iterator j(var_list.begin());
*i; // var型
*j; // const var型
--------------
>>883 どうも助かりました。
命名するまでもないものですがお役に立てば・・・。
おお、できたのね。お疲れ様。
889 :
デフォルトの名無しさん:02/11/07 23:52
VC6 + stlportで
#include <stdio.h>
を書くと
stlport\stdio.h(22) : fatal error C1083:
インクルード ファイルがオープンできません。'../include/stdio.32771'
というエラーが出ます。
該当する行は
# include _STLP_NATIVE_C_HEADER(stdio.h)
です。
こんなエラーって出たこと有る方いませんか。
解決法を教えてください。
出たことないねえ。
STLPortはどこに入れてるのさ。
>>889 そういう時は-P付けてプリプロセッサの出力見れ。
うちだと
>#line 463 "c:\\ap\\devel\\vs6\\vc98\\include\\../include/stdio.h"
となってて、試しに環境変数INCLUDEをunsetしたら同じエラーが出た。
つまり、vcvars32.bat実行するなり手動で設定するなりしろボケ、と。
892 :
デフォルトの名無しさん:02/11/09 23:27
STLPort使ってる方
使うときのネームスペースどうしてます?
他の環境(社内の違う人)に渡すときに
STLPortを使ってることをわかりやすいように
_STL:: を使ったほうがいいですかね
893 :
デフォルトの名無しさん:02/11/10 01:03
>>892 無駄
STLportをわかってる人ならそんなん要らん。
STLportをわかってない人ならそんなん意味ふめ。
でさ、もーわかったと思うけどSTLPortじゃなくて STLport な。
>>893 ヤクザ(((( ;゚Д゚))))ガクガクブルブル
ってかくだらねーことツッコみすぎ
896 :
デフォルトの名無しさん:02/11/12 20:16
>>891 意味がわかんないのですが
環境変数 INCLUDE に stlport のフォルダを設定するって事?
なぜエラーが出るの?
int main()
{
std::vector<int>* vect;
vect = new std::vector<int>;
vect->push_back(1);
vect->push_back(4);
vect->push_back(2);
vect->push_back(3);
vect->push_back(5);
std::for_each(vect->begin(), vect->end(), std::ostream_iterator<int>(std::cout, " "));
}
std::for_each じゃなくて std::copy をつかう。
>>898 ありがとうございます〜。大きな勘違いをしてました。
std::for_each()を使ってみたら、今度は「呼び出しに余分なパラメータがある」
と叱られてしまいました。どうしてでしょうか?わかりません。
template <typename T>
struct test : public std::unary_function<T, void> {
void operator()(T p) {
std::ostream_iterator<T>(std::cout, " ") = p;
}
};
int main()
{
std::vector<int>* vect;
vect = new std::vector<int>;
vect->push_back(1);
vect->push_back(4);
vect->push_back(2);
vect->push_back(3);
vect->push_back(5);
test<int> t();
std::for_each(vect->begin(), vect->end(), t); // test<int>()とすると通る
delete vect;
}
900です。自己解決しました。
test<int> t(); → test<int> t; とすると通りました。
しかし、なぜだろう?関数オブジェクトじゃないのか?
FAQ だな。test<int> t(); だと t は関数宣言とみなされちゃうから。
>>902 なるほど。宣言の形が関数をしているからですね。しかし、次の例では
関数オブジェクトと見なされるようです。うーん難しい。
template <typename T>
struct test : public std::unary_function<T, void> {
test(T v = 0) : val(v) {}
void operator()(T p) {
std::ostream_iterator<T>(std::cout, " ") = p * val;
}
private:
T val;
};
int main()
{
std::vector<int>* vect;
vect = new std::vector<int>;
vect->push_back(1);
vect->push_back(4);
vect->push_back(2);
vect->push_back(3);
vect->push_back(5);
test<int> t(2);
std::for_each(vect->begin(), vect->end(), t);
delete vect;
}
そりゃ、「2」は型じゃないからね。関数宣言には解釈できない。
>>904 本当ですね。実はt(int); とやったらコンパイルは通るものの、
リンク時にエラーが出て首をひねっていたんですよ。
そういう事だったのか。関数オブジェクトに対する理解が一つ深く
なりました。
Effective STL に関連>902-905に関する項があったような。
正しい対処法も載ってたけど、コンパイラによってはその「正攻法」が使えず、
汚い書き方しかでけへん、と嘆いていた記憶が。
Item 6 だね。
std::ptr_fun使うことで、std::not1などのファンクタが通常の関数にも
使えるようになるのは初めて知った。
>>896 コマンドラインからコンパイルしようとしてるんだろ?
だったらVC++のコマンドラインコンパイラ用の設定をちゃんとやれ、
という事。設定方法が分からないなら「vcvars32.bat」でヘルプ検索
でもしろ。
某過去ログ見ててこんなの(↓)思い付いたんですが、
配列の初期化を、コンパイル時に自動的に生成する方法って無いですか?
#include <iostream>
#include <vector>
using namespace std;
typedef void __cdecl FUNC(void);
typedef FUNC* PFUN ;
template<int n> struct f{ static FUNC f_; };
enum Id{ MOGE, HOGE, HAGE, SAGE, maxId };
template<MOGE> void f<id>::f_(void) { cout<<"MOGE"<<endl; }
template<HOGE> void f<id>::f_(void) { cout<<"HOGE"<<endl; }
template<HAGE> void f<id>::f_(void) { cout<<"HAGE"<<endl; }
template<SAGE> void f<id>::f_(void) { cout<<"SAGE"<<endl; }
// ↓を自動化したい!
PFUN funcTable[maxId] = { f<0>::f_, f<1>::f_, f<2>::f_, f<3>::f_ };
void main()
{
for(int k=0; k<maxId; ++k ) funcTable[k]();
}
template<> void f<MOGE>::f_(void) { cout<<"MOGE"<<endl; }
template<> void f<HOGE>::f_(void) { cout<<"HOGE"<<endl; }
template<> void f<HAGE>::f_(void) { cout<<"HAGE"<<endl; }
template<> void f<SAGE>::f_(void) { cout<<"SAGE"<<endl; }
UP用に書き換えた時ミスったっス。
913 :
デフォルトの名無しさん:02/11/17 03:42
std::random_shuffleを使った所、「未定義の関数 'rand' を呼び出した」という
エラーが出ました。
このエラーは、もちろんalgorithm.h中でrand()を呼び出している際に、std::rand()
とせずに単にrand()として呼び出しているせいです。
こういう場合、どうしてもusing namespace std;を付けなければいけないのでしょうか?
それとも、algorithm.hを書き換えるべきでしょうか?
コンパイラはBorland-C++5.5.1 + STLport4.5.3です。
915 :
デフォルトの名無しさん:02/11/17 03:51
>>914 もちろん #include <algorithm> としてあり.hは付けていません。
妥協策として、using std::rand; を入れてエラーを回避しています。
便乗質問になりますが・・・・
std::remove()を使うと、
エラー E2034 9-8-4.cpp 30: 'int *' 型は 'const char *' 型に変換できない(関数 main() )
エラー E2342 9-8-4.cpp 30: パラメータ '__path' は const char * 型として定義されているので int * は渡せない(関数 main() )
エラー E2227 9-8-4.cpp 30: std::remove(const char *) の呼び出しに余分なパラメータがある(関数 main() )
というエラーが出ます。std::remove(const char*)との関数の多重定義がうまく解決できて
ない模様です。STLport独自の名前空間である _STLを使って_STL::removeとすることにより
エラーを回避しています。これも仕方ないのでしょうか?
>>915 STLportのヘッダがそのusing宣言を済ましているはずなのだが・・・。
具体的にrand()って書いてあるのは、
stlport/stl/_algo.c : 434
で、ここはSTLportのnamespaceの中のはず。
>>917 ですよね。でも、だめなんです。うーむ。Borland-C++とSTLportの相性が悪いのか・・・・
>>918 C++Builder6はSTLport採用だそうな。
プリプロセッサ出力を見たらなんかわかるかも。
>>919 その手がありました!今からプリプロセッサ(cpp32.exe)を通して、どのように
展開されているか見てみます。これではっきりしますね。ありがとうございます。
実はC++Builder6も持っています。試してみた所、全く同様のエラーが出ました。
プリプロセッサを通してみました。やはりというか、予想通り、STLportは
using std::randを生成してくれていません。rand()そのものはstd名前空間に
包まれたままです。
using namespace std;を前提に書かれているようです。折角の名前空間
の機能が活かされていないような気がして。
でも、バグと分かれば、割り切って使うことができますね。
>>921 STLportにはnamespaceまわりのオプション(マクロ)が何個かあるから、
ソースとプリプロセッサ出力見ながら、それぞれのオプションの動きを追えば・・・。
めんどくせぇな。
>>922 わかりました。stlport.orgを見てじっくり研究してみます。
#低レベルな質問ばかりしてスマソ。過去ログみて皆さんのレベルの高さにビクーリ。
924 :
デフォルトの名無しさん:02/11/18 19:16
925 :
デフォルトの名無しさん:02/11/19 12:47
vector<string>を順番に連結してひとつのstringにする、綺麗な方法はどんなんすかね
>925
順番てのがわからんけど、
一気に長さカウントして領域確保してコピペじゃだめなの?
927 :
デフォルトの名無しさん:02/11/19 12:55
>>926 iteratorじゃなくてalgorithmでコピーしたいんですが・・
>>927 boost::lambda使えば?
int main()
{
std::vector<std::string> vs;
std::string str;
vs.push_back("abc");
vs.push_back("def");
vs.push_back("ghi");
std::for_each(vs.begin(), vs.end(), str += boost::lambda::_1);
std::cout << str << std::endl;
}
929 :
デフォルトの名無しさん:02/11/19 13:14
ostringstream オブジェクトに ostream_iterator を適用して copy を使えば?
std::accumulate( x.begin() , x.end() , std::string() );
!!
accumulateがstringに適用できるとは思いつかなかった・・・・
935 :
デフォルトの名無しさん:02/11/19 17:32
istreamからCRLF区切りで1行づつ読むにはどうしたらいいですか?
>>935 getline(buf, count);
もし std::stringに読みとるなら std::getline(ifs, str);
938 :
デフォルトの名無しさん:02/11/19 18:22
誰か超便利で芸術的なfor_eachマクロ見せてくれ。
939 :
デフォルトの名無しさん:02/11/19 18:31
>>937 ファイル全体をstringに読む場合で、istream_iteratorを使わない方法で
綺麗なのってどんなんですかね?
>>939 俺はこういう風にしてるけど、algorithmとか使った方がいい?
int main()
{
std::ifstream ifs("filename");
std::string str, tmp;
while (std::getline(ifs, tmp))
str += tmp + '\n';
std::cout << str;
}
ファイル全部をメモリマップして、std::string str( mmapaddr ); (w
>>941 それだったら std::string str(mmapaddr, length); のように長さを与えて
やらないといけないのでは?
ああそうか、C文字列なら終端に'\0'がついているからそのコンストラクタ
を使えばいいのか。
>>941にヒントを得てこんな書き方を考えてみた。
int main()
{
std::ifstream ifs("filename");
std::string str;
std::getline(ifs, str, '\0');
std::cout << str;
}
ガ━(;゚Д゚)━ン!!
getlineなんてものが標準にあったのか…
勉強不足だな…死のう(-_-)
>>938 C++が、ローカルクラスとtemplateを組み合わせて良い仕様だったら
面白い物が書けるんだけどねぇ。
>>947 パラメータの型によってメンバがダイナミックに変化するクラス?
(((( ;゚Д゚))))ガクガクブルブル
おまいら! lisp 使え。lisp
lisp に STL があるんですか???
lispはやだ。遅いから。プログラム読みにくいし
おまいら! 血を吐け。
953 :
デフォルトの名無しさん:02/11/20 06:23
もまえら、次スレはどうしますか?
>>924 じゃあVC++IDEのオプション/ディレクトリ設定でインクルードパスの
設定をちゃんとやる。つか、デフォルトからいじってなければ問題
ないはずだが…
♥♠♫♣☻♥♠♫♣☻
♥♠♫♣☻♥♠♫♣☻
♥♠♫♣☻♥♠♫♣☻
♥♠♫♣☻♥♠♫♣☻
♥♠♫♣☻♥♠♫♣☻
次スレは、もっと Generic なやつをキボン
boost だのなんだのもあつかえるように。
958 :
デフォルトの名無しさん:02/11/20 10:20
STL/Boost/Loki統合スッドレ
希望。
テンプレートライブラリ綜合スレッドってところですな。
タイトルは
C++ ジェネリックプログラミング (STL/Boost/Loki 統合スレ)
あたりでいかが?
もれも見難いので統一キボンヌ。
C++にそんなに沢山スレは要らないと思う。
>>948 boost::any とか、それにちかいことやってんじゃん。
しかし、もともと Boost スレはこのスレから分裂したんじゃなかったか?
964 :
デフォルトの名無しさん:02/11/20 15:35
>>948 ナニにガクガクしてんだかわからん・・
>>963 しかし、「(STLで)どのようにかけますか?」「xxxですが、boostならもっと楽でxxx」
みたいなやりとりが多いのも事実。再統一してもいいな。
>>964 まあ、漏れは別にどっちでも構わん。
もともとどっちも進行の遅いスレだし。
漏れも統一に一票。
細分化されすぎるとワケワカラン。
誰か新スレをSTLで作ってくだちい。
>>966 「新スレですが、boostならもっと楽に新スレッド作れますよ。」
乙
誰もいない・・・。
あまぐりむいてもらうならイマノウチ
| ___|_ | |
_ー|ー-ー | _ ヽ \ | |
__|_」  ̄~| ̄ / レ |
/ |ノ ^ヽ _.、| < ノ
(_ノ| ノ ∠_ノ\ \ /
. _」__  ̄──
_| \ | ヽ /
(ノ^|. | | |
(_._」 レ / \
●
ヽ(;´Д`)ノ
| ___|_ | |
_ー|ー-ー | _ ヽ \ | |
__|_」  ̄~| ̄ / レ |
/ |ノ ^ヽ _.、| < ノ
(_ノ| ノ ∠_ノ\ \ /
. _」__  ̄──
_| \ | ヽ /
(ノ^|. | | |
(_._」 レ / \
●
ヽ(´Д`;)ノ
ほい。
○
ミ∴
∴∴
ホントウニ ムカレテ シマッタ Σ(゚д゚lll)ガーン
977 :
デフォルトの名無しさん:02/12/07 17:56
auto_ptrにコピーコンストラクタはないもんなの?
mapにinsertしたいんだけどどうすればいいの?
>>977 std::auto_ptrにはコピーコンストラクタはありますが、通常のコピーコンストラクタ
と意味が違い所有権の譲渡があります。
コンテナにstd::auto_ptrを挿入するのはCOAPと呼ばれ、動作が保証されないばか
りでなく、挿入そのものを禁止しているSTL処理系があります。
コンテナにスマートポインタを挿入したければboost::shared_ptrを使いましょう。
>>978-980 ありがとうございます。
早速よんでみます。
ところでこのスレはつぶさないの?
放置でDat待ち?
982 :
デフォルトの名無しさん:02/12/08 00:31
auto_ptrにコピーコンストラクタはないもんなの?
mapにinsertしたいんだけどどうすればいいの?
timpo_ptr にコピーコンストラクタはないもんなの?
mamco に insert したいんだけどどうすればいいの?
>>983 何も被せず生のままinsertする事が推奨されてます。
まさにgenericなんてナ。
>>983 そのmamcoコンテナは、要素の出し入れを繰り返すと、だんだん中に入る要素の数が
増える不思議なコンテナだよ。
>>984=985
まだ generic に手を出すには時期尚早なんで、
スマートポインタskin_ptrでwrapしておきまつ・・・
>>986 空間確保を繰り返すと、確保に慣れて始めから多目に空間を確保
するようになるというコンテナであると聞きますた。
ホントにmamcoみたいなコンテナあったら面白いカモ(w
最初は、insertしようとすると例外が投げられるかもなー・・・。
Out Of Gancyu Exception が一番きついわな。
復帰不可能だ。
# ・眼中にない completely ignore
obsolete
obsoluteなのか?
じゃあ最近の流行は
NoMoneyExceptionか?
NullpoException
StdExceptionをskin_ptrなしで挿入すると
コンテナがStdExceptionに汚染され、
StdExceptionに汚染されたコンテナへ挿入時に
StdExceptionをキャッチしてしまうと
挿入アイテムがStdExceptionに汚染されます。
そして StdException は当然 SEX と略すのですね?(w