【C++】template 統合 ..
237:デフォルトの名無しさん
05/01/11 00:57:13
>>219
引くってのはどうよ。
for(element = test.begin(); element != test.end(); ++it)
{
if(*element == 2){
test.erase(element--);
}
}
あ、でも element = test.begin(); element--; は大丈夫なのかな。
まぁ、EffectiveSTLを読んでいれば test.erase(remove(),test.end())と書くというのに一票。
238:237
05/01/11 00:58:59
訂正。
>>237
++it => ++element
239:デフォルトの名無しさん
05/01/11 01:06:22
>>237 ダメ
240:デフォルトの名無しさん
05/01/11 14:28:58
for(element = test.begin(); element != test.end(); ++element)
if(*element == 2)
{
element = --test.erase(element);
}
こんな感じが一番シンプルなところなのかな?
241:デフォルトの名無しさん
05/01/11 15:04:23
removeとeraseの組み合わせが一番シンプル
242:デフォルトの名無しさん
05/01/11 15:59:47
とりあえずremoveとeraseの組み合わせが何でも一番です(^^
243:デフォルトの名無しさん
05/01/11 16:01:18
clearって手もあるよ
244:デフォルトの名無しさん
05/01/11 19:46:02
>>223
プロジェクトって大抵いろんな技術レベルの人がいるから
その台詞でばっさりはちょっと抵抗あるなぁ。
一人でやるなら何使ったってOKだけどね。
245:デフォルトの名無しさん
05/01/11 20:32:55
>>244
211はかなり基本だと思うんだけど...
246:デフォルトの名無しさん
05/01/11 20:46:56
あれが解からないって?
…ときどき思うんだ。俺、なんで2chなんか見てるんだろう、って。
247:237
05/01/11 22:30:46
なんか不安になってきたので確認したいのですが
vectorのeraseで無効になるのは消した要素以降のイテレータですよね。
だから>>237と>>240は結果的に同じことになりますよね?
私が>>237で心配だったのは
最初の要素でヒットしたとき、
element = test.begin();
--element;
++element;
でbegin()に戻るのが規格で保証されてなさそう(多くの実装では戻りそうだけど)
というのと
元々のサイズが1のとき、test.erase(test.begin());で全てのイテレータが無効になる
ときにバッファを解放してbegin()とend()がNULLを返してくるようになるとend()と
永遠に一致しなそう(VC7のclearがバッファを解放(capacityを0)にしてくれるのに
気づいて以来疑り深くなっています)
の二点なんですけど、
そのあたりをふまえて>>239はダメと言っているんですよね?
うーん、remove(や類似のアルゴリズム)を使わないでやるならやはり>>219なのか。
248:237
05/01/11 22:34:15
ああ、そうか、後者の不安は>>240と書くことで払拭されるのか。
スマソ
249:244
05/01/12 01:12:53
>>245
俺も基本だと思ってるし、これぐらいわかれよって思ってるよ。
でも、それが通用しないのが多人数でしょ?って投げかけ。
…技術と関係なくなるか。消えるよ。スレ汚しすまん。
250:デフォルトの名無しさん
05/01/12 02:17:30
なぜforで回す……わざわざC++使うんだったら、効率にも気を
配らないともったいないよ。
>247
>237 >240の例だと
・ループごとにtest.end()の呼び出しが発生する
・elementを削除するたびにvectorの再パッケージが発生する
で遅くなりますな。
あと、>237だと後置インクリメントの一時オブジェクトの生成が
発生してさらに効率が悪くなります。
251:デフォルトの名無しさん
05/01/12 02:18:18
なぜにremoveを使いたくないのかが知りたい
252:250
05/01/12 02:24:13
自己フォロー
>237>240ともに、はelement==test.begin()のときに
*element==2だとアウトですな。
#test.begin()よりも前に移動するから未定義の世界に突入
253:デフォルトの名無しさん
05/01/12 02:48:28
>250
ループごとのtest.end()も後置インクリメントもここでは本質じゃない。
254:デフォルトの名無しさん
05/01/12 02:56:25
>253
ふうん、じゃ、こう言っておこうかな
・郷に入れば郷に従え
STLはC++の一部なんだから、それぐらい覚えろ
・こんぐらいできないなら、そもそもC++使うな
or こんなこともできないやつをプロジェクトに入れるな
他にもPerlとか色々あるんだから、わざわざC++を使う必要ないよね。
255:デフォルトの名無しさん
05/01/12 07:36:48
list に追加されている remove(),remove_if() 見習って、
template<class Container> void remove(Container&, typename Container::value_type const&)
template<class Container, class Predicate> void remove_if(Container&, Predicate p);
のような関数を作れば、双方文句はなかろう。
256:255
05/01/12 07:50:40
s/Container/Sequence/
remove() の意味が混乱を招きやすいという認識はSGIのドキュメントにも記載されている。
「慣用句だ」と言って押し切るよりは、むしろまともな認識だと思う。
URLリンク(www.sgi.com)
これをそのままソースに書いてしまうと言うのは、
例えば定数除算をシフトで書いてしまうのと同等の誤りであると思う。
257:デフォルトの名無しさん
05/01/12 07:51:49
forで回すからうっかり>>218とか>>237とか>>240とかいう問題のあるコードを書いて
しまうんだよ。
だったらおとなしくremoveを使えと。
まぁ、色々書き方があってその中から適切な物を状況に応じて選ぶのがプログラムの
醍醐味ではあるけど。
258:デフォルトの名無しさん
05/01/12 08:53:47
>なぜにremoveを使いたくないのかが知りたい
叙述関数やoperator==とかにコードが分散するのがイヤ
ループが内包されるのがイヤ ループを制御下に置いておきたい
ブレイクポイントが設定しやすいよ
削除以外の用途にループが流用できるよ
てゆうかぶっちゃけremove_copy中でやってること、あれはありえないでしょ
それを言ったらvectorでeraseすること自体ありえないかw
259:デフォルトの名無しさん
05/01/12 09:59:55
>ループが内包されるのがイヤ ループを制御下に置いておきたい
ループを明示的に書くより効率が良くなる可能性があるし、
コードの見通しも良くなる
260:デフォルトの名無しさん
05/01/12 10:06:05
>>254
「理想郷」との差でしかモノを語れない
頭でっかちの引き籠もりはレスしなくていいです ;-)
261:デフォルトの名無しさん
05/01/12 10:32:21
>260
それ、オレじゃない。人違いだ
262:デフォルトの名無しさん
05/01/12 10:48:33
>260
IDくらい見ろ、ボケ!
263:デフォルトの名無しさん
05/01/12 11:10:58
>>262
この板ID無いんだって気付よ!
264:デフォルトの名無しさん
05/01/12 11:21:54
お前さんたちなんか楽しそうだね。
265:デフォルトの名無しさん
05/01/12 11:42:25
IDの見方知らない香具師ってまだいたんだね
266:デフォルトの名無しさん
05/01/12 12:13:29
はっきりいってvectorに限らず配列っぽいデータ構造を使っている時に
removeみたいなアルゴリズムを適用したくなることってあるか?
無理して適用しておもしろいことがあるようなものでもないと思うのだけど…
何か見落としている革新的な理由でもあったりするのだろうか?
267:デフォルトの名無しさん
05/01/12 23:55:01
> removeみたいなアルゴリズムを適用したくなることってあるか?
配列から複数の要素を一度に取り除きたいときだな。
268:デフォルトの名無しさん
05/01/13 00:11:28
簡単
let remove x num = snd (List.partition (fun a -> a=x) num);;
269:デフォルトの名無しさん
05/01/14 14:04:12
>>268
配列っぽくないデータ構造。
270:デフォルトの名無しさん
05/01/15 01:33:25
>>267
そそ、端からeraseしてると効率悪いし、
効率的な処理にしようとすると意外に面倒。
271:デフォルトの名無しさん
05/01/17 09:41:54
俺も小さくて、しかもあまり使わないような関数を分散させるのが嫌いなんだけど、
「リファクタリング」を読むと、一行処理すら場合によっては関数にすることを推奨してるんだよな。
しっかりした関数名をつけることによって可読性が高まるって話なんだけど、
必ずしもそうとは思えないのは、英語圏ネイティブじゃないせいかね。
と、templateスレに書き込もうとしたのだけど、主旨に合わないのでこっちに投棄
272:デフォルトの名無しさん
05/01/17 09:43:01
C++スレに書くつもりが…
もうどうでもいいや
273:デフォルトの名無しさん
05/01/17 13:41:34
リファ〜に書いてあるのは関数じゃなくてメソッドのことでは
何の分類もしない単独の関数増やしてくのはあんま良いとは思えないが
メソッドの場合インターフェース抽出とか階層整理とかで意味がある
274:272
05/01/17 17:58:06
>>273
失礼、つい関数と呼んじまう。
インターフェース抽出や階層整理は、それ自体をメインにして行うべきな気がするんだよねぇ。
それどころかそれ以前で、非道い話だが「たくさんの、たった数行のメソッド」ってだけで、嫌悪感を感じてしまう。
いずれにせよスレ違い申し訳ない。
275:デフォルトの名無しさん
05/01/18 00:41:35
>>273
そんな区別ないだろ。
少なくともC++ではthisポインタの有無しか違いはないわけで、
それが関数分けの基準に影響するとは思えない。
276:デフォルトの名無しさん
05/01/18 01:35:22
時々272のような人いるよね。
読むときあっちこっちの関数みないといけないから、とか言って。
このヘタレが
277:デフォルトの名無しさん
05/01/18 01:45:39
そもそも行数とか関係ないだろ
278:デフォルトの名無しさん
05/01/18 02:41:33
>275
その他にも可視性とアクセス範囲に違いがあるわけで……
279:デフォルトの名無しさん
05/01/18 08:17:20
>>278
そうだな。
それらが要るならクラス作ってメンバ関数を作ればいいし、
要らないならフリー関数にしてもいい。
どう整理するかどうかが違うだけで、
処理に名前をつけてまとめたほうがよいかどうかの基準には関係ない。
複数のフリー関数を作った後に、さらに
それらをまとめてクラスを作ればよいことに気付くことも考えられる。
思い立ったらさっさと名前付けてまとめれ。
渋る意味がわからん。
280:272
05/01/18 08:20:53
ちとスレ違い悪いんでこっちでレス
スレリンク(tech板:41番)
281:デフォルトの名無しさん
05/01/21 18:18:02
お聞きしたいのですが、
下記(次レス)のコードがVC7.1でコンパイルできませぬ。
どこがいけないのでしょうか…
色々実験してみた結果
・UINT を int にすると通る。
・UINT を std::size_t にしてもダメ。
・typename T を削除して、 boost::array の T を int とかにすると通る。
・boost:array の nSize を適当な数値で直打ちすると通る。
・bcc5.5.1 では普通に通る。
282:281
05/01/21 18:18:34
#include <boost/array.hpp>
typedef unsigned int UINT;
template<typename T, UINT nSize>
class A
{
typedef typename boost::array<T, nSize> tObjects;
typedef typename tObjects::iterator tObjectsIt;
tObjects m_cObjects;
public:
tObjectsIt Func();
};
// ↓C2244:関数の定義を既存の宣言と合致させることができませんでした。
template<typename T, UINT nSize>
inline typename A<T, nSize>::tObjectsIt A<T, nSize>::Func()
{
return m_cObjects.begin();
}
283:デフォルトの名無しさん
05/01/21 20:49:28
>>281
手元にVC7.1もboostもないし、よくわからんけど、
コンパイラがバグってることはよくあるからw
284:デフォルトの名無しさん
05/01/21 20:57:34
>>282
g++(3.3.3)ではなんの警告もエラーもなく通るのぅ……
285:デフォルトの名無しさん
05/01/21 21:31:52
>>282
戻り値を素直に
typename boost::array<T, nSize>::iterator
とすると通りますね。
286:デフォルトの名無しさん
05/01/22 00:57:24
typedefがprivateなのにinlineなのがいけないんじゃないのか?
と試してもないのに言ってみる
287:281
05/01/22 11:00:38
やはり、コンパイラが悪い方向なんですか… orz
なお、>>286を参考に、
すべてのメンバをpublic にしてみてもコンパイルが通りませんでした。
しょうがないので、現状では
・class内に直書き
・>>285 の方法
の2点で回避したいと思います。
どうもありがとうございました。
288:デフォルトの名無しさん
05/01/22 11:27:55
いまだにちゃんと動かないコンパイラ多いのかよ
おまえらC++信用できますか?
289:デフォルトの名無しさん
05/01/22 11:28:34
C++なら信用できるよ。
290:デフォルトの名無しさん
05/01/22 15:39:27
>>282
vc8 でもダメっぽい
291:デフォルトの名無しさん
05/01/23 15:44:13
boost::bindはstd::bind2ndとかより実行速度が落ちるって本当ですか?
292:デフォルトの名無しさん
05/01/23 16:18:47
>>291
ためして、みなさいって。
293:デフォルトの名無しさん
05/01/23 16:20:48
using句が,による複数引数を受け付けないのは何故ですか?
using A::AA, A::AB, A::AC;
のように出来たら便利だと思うのですが?
294:デフォルトの名無しさん
05/01/23 17:06:31
本スレの次スレ
【標準C++】C++相談室 part39【STL含む】
スレリンク(tech板)
295:デフォルトの名無しさん
05/01/23 17:51:32
>>293
そんなんオレらに聞かれても困るよ
296:デフォルトの名無しさん
05/01/23 17:57:05
>>293
プリプロセッサマクロを書くとか?
あんまり便利とも思えないけど
297:デフォルトの名無しさん
05/01/23 22:42:53
boost(かSTL)に、次のような関数テンプレートって含まれていませんか?
template<typename T>
inline void assign(T& lhs, const T& rhs)
{
lhs = rhs;
}
次のような感じで、setterを用意していないメンバ変数(m_is_foo)を変更する関数オブジェクトを作るのに使いたいのです。標準であるならそっちを使いたいなと思いまして。
hoge(boost::bind(assign<bool>, boost::ref(m_is_foo), true));
298:デフォルトの名無しさん
05/01/23 23:01:05
>>297
試してないけど、 hoge(boost::lambda::var(m_is_foo) = true) じゃだめ?
299:297
05/01/23 23:16:36
>>298
> 試してないけど、 hoge(boost::lambda::var(m_is_foo) = true) じゃだめ?
いけました。サンクスです。
うーん、lambdaか…。主観ですが実戦投入はちょっと怖いんですよね。
300:デフォルトの名無しさん
05/02/07 09:18:51
ふぇ〜い
Boostを最新リリースにしたら@VC6
_bvector.hでコンパイラが内部エラー起こしてビルドできない
Releaseビルドなら通った
コンパイラもしょっちゅう固まるし
やっぱ テンプレートをプリコンパイルヘッダにしたのが悪いのかな ・・
301:デフォルトの名無しさん
05/02/07 09:23:19
日記はMeadowにでm(ry
302:デフォルトの名無しさん
05/02/07 09:28:51
>>300
ヘッダのインクルード順序を変えてみれ。
自分は面倒なので#ifとか使ってインクルード順序をすぐに変えられるようにしてる。
例:
#if 0 //ここを1にしたり0にしたりする。
#include <boost/regex.hpp>
#include <algorithm>
#else
#include <algorithm>
#include <boost/regex.hpp>
#endif
303:デフォルトの名無しさん
05/02/07 14:42:53
Meta-Programming 専用のスレってない?
304:デフォルトの名無しさん
05/02/07 17:41:03
あったけど、ここに統合。
305:デフォルトの名無しさん
05/02/11 13:36:27
テンプレートを使ったクラスでundefined referenceがでます。
ソースは次のようなものです。プリプロセッサは省略してあります。
//temptest.h
template<class T> class temptest{
public:
temptest();
};
//temptest.cpp
template<class T> temptest<T>::temptest(){}
//main.cpp
int main(){
temptest<int> t;
return 0;
}
gccでは "undefined reference to `temptest<int>::temptest(void)"
VisualC++6では "public: __thiscall temptest<int>::temptest<int>(void)は未解決です"
というエラーです。
ちなみに定義をインラインにしたらうまくできました。
どなたか解決方法を教えてください。
306:デフォルトの名無しさん
05/02/11 13:40:12
>>305
templateの定義はヘッダに書かないとダメ、ということになってます。
307:304
05/02/11 13:50:47
そんな決まりがあったんですか。
でもSTLのインクルードファイルを見たところ宣言だけのようですが、
STLは特別なんでしょうか。
308:デフォルトの名無しさん
05/02/11 13:52:15
STLもヘッダの下のほうに書いてあるんじゃねーの
309:デフォルトの名無しさん
05/02/11 13:52:42
STLも例外ではないよ
クラステンプレートに実体がなくてもその後ろにクラスメンバのテンプレートの実体が定義されてるはず
310:デフォルトの名無しさん
05/02/11 14:13:29
stlportだとcppをヘッダからincludeしてたとおもう
311:デフォルトの名無しさん
05/02/11 14:44:21
ヘッダからcppをインクルード・・・萌えるな。
312:デフォルトの名無しさん
05/02/11 15:04:53
>>307
temptest.cpp コンパイル時には class T が何だか解らないので
コンストラクタは生成されない
↓
main.cpp コンパイル時には temptest<int> のコンストラクタが
どこかにあるものとしてコンパイル
↓
リンクしてみたら、どこにもいない
明示的にインスタンス化するよろし。
//temptest.cpp
template class temptest<int>;
313:デフォルトの名無しさん
05/02/11 16:01:01
exportキーワードをまともに実装した処理系はComeau C++だけでしょ。
314:デフォルトの名無しさん
05/02/11 19:41:42
もう諦めてexportを標準から外した方が良いんじゃないかとさえ思ったり.
現状,exportによる利得というのがほとんど無いみたいですし.
315:デフォルトの名無しさん
05/02/11 21:11:04
つーか既に実装しなくていいよもう、ってことになったんじゃなかったか?
316:デフォルトの名無しさん
05/02/11 21:50:10
>315
ソースきぼんぬ.
export周りは泣きそうなほどグダグダみたいですし,さもありなんですけど.
317:デフォルトの名無しさん
05/02/11 22:10:19
それがC++クオリティ
318:デフォルトの名無しさん
05/02/12 06:49:19
>>316
D&E日本語版読んでみ。
exportは未だに実装してないといけない規格になっている。
319:デフォルトの名無しさん
05/02/12 19:42:14
exportって何?
320:デフォルトの名無しさん
05/02/12 19:42:57
るby
321:デフォルトの名無しさん
05/02/16 10:47:32
shared_ptrとかintrusive_ptrのリファレンスカウント操作って
引数で値渡しすると呼び出しのたびに操作しますよね。
最適化によるコード削減を阻害しないでしょうか?
特にテンプレートを展開したもののコードがどうなるかが気になります。
322:デフォルトの名無しさん
05/02/16 11:26:01
>>321
適材適所で。
それからテンプレートの勉強もね。
323:デフォルトの名無しさん
05/02/16 11:38:00
>>322 要するにオーバーヘッドはかかるというお答えという理解でよろしい?
intrusive_ptrの参照を渡せばいいんですけど、ポインタの置き換えに使うつもり
でいるといまひとつ面倒というか泥くさいというか。
あと、これらのコンテナをfor_eachなどで処理するときのbind(+lambda)で、
_1 と書くだけじゃdeductionしてくれず、bind(&HogePtr::get, _1)
のようにしないといけないのが面倒で、
これを何とか自動でやってくれるようにする方法はありませんか。
HogePtrという派生クラスを作ってポインタから暗黙的にキャストさせると
一番簡単にコンパイラを黙らせられるんですが、今度はコンテナを処理するときに
毎回HogePtrを作って比較するというコードを出してくるようになるので、
なるべく派生はさせずに済ませたい。
324:デフォルトの名無しさん
05/02/16 20:11:57
参照カウンタによるオーバーヘッドが許せないのなら、
shared_ptr系は精神衛生上使わないほうがいいと思う。
325:デフォルトの名無しさん
05/02/17 00:41:46
>>323
bind の件は既に修正済みのはず。
326:デフォルトの名無しさん
05/02/17 14:17:53
>>323
恐ろしいことだが君のようなハッカーには
それらはもうレガシーだ。boostなのにね。
sandboxにModern C++ Designのを移植した
policy_ptrというのがあるので見るべき
これはなかなか強烈だよ
327:デフォルトの名無しさん
05/02/18 02:14:48
>>326
お前は独逸の詩人かよ!?
328:デフォルトの名無しさん
05/02/18 12:12:10
>>326
ポリシーベースの派、前に検討して却下してshared_ptr達が採用されたのに
なんで今更?
329:デフォルトの名無しさん
05/02/18 20:40:47
>328
その議論読んでみたいんですがどこにありますか?
policy_ptrは「shared_ptrは重い」といった主張を持つユーザに対する
選択肢の一つとして提供されるのだと思いますよ.
そもそもpolicy_ptrはshared_ptrなどの既存のスマートポインタに取って代わるものではなく,
むしろそれらと相補関係にあって共存するべきものですし.
なのでshared_ptrを"legacy"と表現するのは恐らく適切ではないです.
ここら辺のもう少し詳しい議論は以下のスレッドや
policy_ptrのドキュメントのFAQあたりが参考になると思います.
URLリンク(thread.gmane.org)
330:デフォルトの名無しさん
05/02/18 21:19:44
似たような*_ptrばっか増やして、
馬鹿じゃないの?
ふざけてるの?
331:328
05/02/18 21:23:27
>>329
URLリンク(boost.cppll.jp)
の2番目を。
332:デフォルトの名無しさん
05/02/18 23:38:55
>>330
C++ ってそういうもんだよ。人によって用途も違えば、実行環境のリッチさも
天と地ほど違うので。
333:デフォルトの名無しさん
05/02/22 15:00:52
新規にクラスを作るならば、COM のように侵入型の参照ポインタにして、
intrusive_ptr で管理するとか
334:デフォルトの名無しさん
05/02/22 17:27:12
STLかboostあたりに、ある条件を満たすものをoutput_iteratorにコピー
するような関数はないでしょうか?
boost::mplにcopy_ifというそれらしい名前のがあるんですが、
使い方がさっぱりわからない……
335:デフォルトの名無しさん
05/02/22 17:40:29
なぜか std に copy_if ないんだよね・・・
boost::filter_iterator と std::copy でなんとか汁
336:デフォルトの名無しさん
05/02/22 17:43:19
std::remove_copy_if(first, last, std::not1(pred));
337:336
05/02/22 17:43:58
ごめん。
std::remove_copy_if(first, last, out, std::not1(pred);
だ。
338:デフォルトの名無しさん
05/02/22 18:06:02
今回は元のコンテナを変更したくないのでremove_copy_ifは使えなさそうです。
結局自分で書きました。
自分でforループを書くと頭悪くなったように感じるので、
これくらいstdに入れておいてほしいものです……。
template <class InputIterator, class UnaryFunction, class OutputIterator>
void copy_if(InputIterator begin, InputIterator end,
OutputIterator result,
UnaryFunction pred) {
for ( ; begin != end; ++begin)
if (pred(*begin)) {
*result = *begin;
++result;
}
}
g++のヘッダを見るとconcept checkとやらを入れたほうがいいらしいのですが、
何を使えばいいのかよくわからんです。boostに道具があるんでしょうか。
remove_copy_ifも説明がよくわからんのですよね。
削除するのに大きさが変わらないってどういうこと?
339:デフォルトの名無しさん
05/02/22 18:06:58
>>338
remove_copy_ifは入力シーケンスを変更しないよ。
340:デフォルトの名無しさん
05/02/22 18:17:58
>>338
return result;
341:一つ賢くなった!
05/02/22 18:32:43
>>339
おお、本当だ。コードを見るとほぼそっくりではないですか。
今までremove_copy_ifは元のを破壊的に変更しつつ、削除したものを
コピーするのだと思っておりました。
名前がミスリーディングだと思うのです……。
>>340
忘れてました。というか気にしてなかったのですが、返すべきですね。
342:デフォルトの名無しさん
05/02/22 19:24:56
struct NURUPO
{
template<typename T> operator T*() { return 0; }
};
int ILoveNurupo()
{
NURUPO mynurupo;
return (int)mynurupo[0];
}
vc7.1とgcc3.3にガッ
343:デフォルトの名無しさん
05/02/22 21:10:19
なんか違わないか?
344:デフォルトの名無しさん
05/02/23 01:38:28
>>338
STLPortには入ってるよ。
345:デフォルトの名無しさん
05/02/24 14:00:35
テンプレートの特殊化ってどこに書きますか?
以下のように特殊化する型の定義と一緒に書くと、
* primary.h
#include <iostream>
template <class T>
inline void foo(const T&) { std::cout << "primary\n"; }
---
* specialized.h
#include "primary.h"
struct bar {};
template <>
inline void foo(const bar&) { std::cout << "specialized\n"; }
---
* troublesome.h
struct bar;
bar& get_bar();
346:345
05/02/24 14:01:58
* troublesome.cpp
#include "specialized.h"
bar& get_bar() { static bar b; return b; }
void trouble1()
{
foo(get_bar()); // #1
}
---
* main.cpp
#include "primary.h"
#include "specialized.h" // #2
#include "troublesome.h"
int main()
{
foo(get_bar());
return 0;
}
---
#1 と #2 をコメントアウトしたりしなかったりで実行結果が変化します。
具体的には #1 と #2 の両方をコメントアウトした場合 primary が出力されます。
かといって、極端な話 STL のヘッダファイルに書き足すわけにもいけませんし・・・。
347:デフォルトの名無しさん
05/02/25 00:39:40
>>345
URLリンク(www.kuzbass.ru)
14.7.3 -6- および -7- で、
使う場所より前に特殊化は宣言されていないといけない、
というルールは書いてあるが、コンパイラによるチェックは不要ということになっている。
あげくに規格中に「宣言の位置には気をつけろ」と書かれている。
primary.h の foo<T> の中でダミーでいいから sizoef(T) を使って、
不完全型ではインスタンス化できないようにしておけば、
いちおうエラーにすることができると思う。
348:デフォルトの名無しさん
05/02/28 11:44:49
template<class T> class A
{
public:
void hoge() { }
void foo() { }
// 他にいろいろなメンバがある
};
というクラステンプレートがあって、プログラム中でA<T>::hogeだけどこからも使われなかったとき
A<T>::hogeのコードは生成されるのでしょうか?
349:デフォルトの名無しさん
05/02/28 12:01:34
>>348
されない。だから定義しなくても大丈夫。
350:デフォルトの名無しさん
05/02/28 19:22:11
>>348
処理系依存
351:デフォルトの名無しさん
05/02/28 21:47:50
>>350
ほんと?
352:デフォルトの名無しさん
05/02/28 22:10:33
一応標準としてはAの暗黙のインスタンス化ではhogeはインスタンス化されません.(14.7.1/1)
ちなみにAの明示的インスタンス化の際にはhogeのインスタンス化が伴います.(14.7.2/7)
353:デフォルトの名無しさん
05/02/28 22:10:41
>350は狼少年
354:デフォルトの名無しさん
05/03/01 22:32:51
>>348
Modarn C++ Designの1.8に、生成されないことを前提にした技法があったな確か。
シンタックス・チェックだけは、実装によっては行われるんだったっけか。
355:デフォルトの名無しさん
05/03/02 01:29:19
Modern ね
356:デフォルトの名無しさん
05/03/02 12:31:04
スマソ
357:デフォルトの名無しさん
05/03/08 02:55:11
AdobeのASLもここでいいんかな?
358:デフォルトの名無しさん
05/03/08 10:23:35
使われているプログラミング技法を語るならここかな
あるいはBoostスレか
359:デフォルトの名無しさん
05/03/09 18:17:53
以下のコードで complex を set に入れようとしたところ、
「stl_function.h:197: error: no match for 'operator<' in '__x < __y'」
とか言われてしまうのですが (g++ 3.3.3)、原因が分かりません。
何がおかしいのでしょうか。
#include <complex>
#include <set>
using namespace std;
bool operator<(const complex<int> &a, const complex<int> &b)
{
return real(a) < real(b) || (real(a) == real(b) && imag(a) < imag(b));
}
int main()
{
set<complex<int> > s;
s.insert(complex<int>(1, 2));
return 0;
}
360:デフォルトの名無しさん
05/03/09 18:39:00
>>359
<set>の中からそのoperator<()が見えていない。しかしoperator<()を
#includeよりも前に持ってくると今度はcomplexが定義されていない。
しかしstd名前空間内部のものを先行宣言することは許されていない。
自分で関数オブジェクトを定義するしかない。
361:デフォルトの名無しさん
05/03/09 18:40:16
namespace std {
bool operator<(const complex<int> &a, const complex<int> &b)
{
return real(a) < real(b) || (real(a) == real(b) && imag(a) < imag(b));
}
}
で通ったけど、これってやっていいことだっけ……?
362:デフォルトの名無しさん
05/03/09 18:56:02
>>360
> <set>の中からそのoperator<()が見えていない。
これは関係ない。どうせグローバルのoperator<は使われない。
363:デフォルトの名無しさん
05/03/09 19:00:21
>>361
結論:ダメ
宣言や定義をstd名前空間に加えてはならない。今回の場合、struct
std::less<>の特殊化も考えられるが、後述の規定によりuser-definedな名前で
特殊化しない限りundefined behaviorとなる。
17.4.3.1 Reserved names -1
It is undefined for a C++ program to add declarations or definitions
to namespace std or namespaces within namespace std unless otherwise
specified. A program may add template specializations for any standard
library template to namespace std. Such a specialization (complete or partial)
of a standard library template results in undefined behavior unless
the declaration depends on a user-defined name of external linkage
and unless unless the specialization meets the standard library requirements
for the original template.
364:デフォルトの名無しさん
05/03/09 19:17:37
>>362
#include <set>
using namespace std;
struct hoge{int x;};
bool operator<(const hoge& a, const hoge& b){return a.x < b.x;}
int main(){
set<hoge> s;
s.insert(hoge());
return 0;
}
これ通らない?
365:デフォルトの名無しさん
05/03/09 21:08:49
>364
それはhogeとoperator<が同じ名前空間(グローバル)で定義されているので通りますよ.
std::complexを引数とする呼び出しからoperator<が見えるためには
operator<がstd名前空間で定義されていないといけないです.
でもそのような定義をstd名前空間に追加することは許されないので(>363),
自分で関数オブジェクトを書いて(>360)それをsetのテンプレート引数に与えるしかないです.
366:デフォルトの名無しさん
05/03/09 21:12:46
で、結局こう、と。
#include <complex>
#include <set>
using namespace std;
template <typename T>
struct complex_less: binary_function<complex<T>, complex<T>, bool> {
bool operator() (const complex<T>& a, const complex<T>& b) {
return real(a) < real(b) || (real(a) == real(b) && imag(a) < imag(b));
}
};
int main () {
set< complex<int>, complex_less<int> > s;
s.insert(complex<int>(1, 2));
return 0;
}
367:359
05/03/09 21:25:39
>>360-366
皆さんありがとうございます。よく分かりました。
ちゃんと勉強しないとダメだなぁ〜 orz
368:デフォルトの名無しさん
05/03/09 21:55:23
string とか pair が std 名前空間に operator < を定義しているから
ADL のせいで operator < を std 名前空間の外に探しに行かないという認識であってますか?
369:デフォルトの名無しさん
05/03/09 22:09:23
↑俺には断言できん
↓あってるのか?
370:デフォルトの名無しさん
05/03/09 22:11:50
あってる。
371:369
05/03/09 23:24:46
>>368
あってるぞ。
よし、俺ツーポイントゲット。
372:デフォルトの名無しさん
05/03/10 04:08:30
その為に less がテンプレート引数になってるんではないのか。
…と、こないだ初めて map で less を使った俺が言いました。
373:デフォルトの名無しさん
05/03/11 02:09:30
練習で push_back_if なるものを書いてみたのですが
駄目だしお願いします。
template <typename IIte, typename Container, typename Pred>
void push_back_if(IIte b, IIte e, Container &c, const Pred p)
{
for(;b!=e;b++)
{
if(p(*b)) c.push_back(*b);
}
}
insert_if とか copy_if ってないんですか?
あったら便利だと思うのですが・・・。
374:デフォルトの名無しさん
05/03/11 02:24:34
copy_ifはある。あとはback_inserterを組み合わせて使えばよし。
375:デフォルトの名無しさん
05/03/11 02:27:17
> copy_ifはある。
ウソだった。標準ではない。すまん。
376:デフォルトの名無しさん
05/03/11 02:36:13
>>373
残念ながらcopy_ifは標準にはない。どっかに作っておいたら?
//copy_if
template <typename InputIterator,
typename OutputIterator,
typename Predicate>
inline
OutputIterator
copy_if(InputIterator begin,
InputIterator end,
OutputIterator destBegin,
Predicate p)
{
while (begin != end)
{
if (p(*begin)) *destBegin = *begin;
++destBegin;
++begin;
}
return destBegin;
}
377:デフォルトの名無しさん
05/03/11 16:52:41
>>373
> for(;b!=e;b++)
++bにしたほうがいい。
378:デフォルトの名無しさん
05/03/11 19:43:05
>377
また荒れるようなことを
379:デフォルトの名無しさん
05/03/11 20:28:43
いやいや荒れるまでもなく当たり前の事ですよ
380:373
05/03/11 21:26:10
>>374-379
レスが遅くなってすいません。参考にします。
381:デフォルトの名無しさん
05/03/13 00:46:27
荒れてもいいから理由を教えろ
382:デフォルトの名無しさん
05/03/13 01:27:48
>>381
後置インクリメントだと、一時オブジェクトが必要になるから。
POD型の場合でもレジスタを余計に必要としたりね。
#それが理由で後置インクリメントを持たないクラスも作ることも多いし。
383:デフォルトの名無しさん
05/03/13 01:32:28
C++より++C
384:デフォルトの名無しさん
05/03/13 01:50:07
> POD型の場合でもレジスタを余計に必要としたりね。
は?
385:デフォルトの名無しさん
05/03/13 03:26:57
今 typeof が使えるコンパイラって g++, icc の他にどんなのがある?
typeofなんてぶっちゃけ template つかってないと殆ど使わんだろうしここでいいよね。
386:デフォルトの名無しさん
05/03/13 09:54:26
RTTIとテンプレートはあまり関係ないだろうと思いつつ、
ほとんどのメジャーなコンパイラは扱えますよ。
387:デフォルトの名無しさん
05/03/13 09:57:05
typeidじゃないよ。
388:デフォルトの名無しさん
05/03/13 12:31:23
メジャーじゃないコンパイラは"ほとんど"に含まれない言葉のトリック
389:デフォルトの名無しさん
05/03/13 13:47:16
そういうもんだいではない
390:デフォルトの名無しさん
05/03/13 17:59:47
#define FOR_EACH(RANGE, ITERATOR) \\
for(boost::range_iterator::< typeof(RANGE) >::type ITERATOR \\
= boost::begin(RANGE); \\
ITERATOR != boost::end(RANGE); \\
++ITERATOR)
int a[3] = {1, 2, 3};
FOR_EACH(a, it){
cout << *it << endl;
}
391:デフォルトの名無しさん
05/03/13 18:00:22
struct plus
{
template<class LHS, class RHS>
typeof(l + r) operator()(LHS const &lhs, RHS const &rhs) const{
return lhs + rhs;
}
private:
LHS l;
RHS r;
};
392:デフォルトの名無しさん
05/03/13 18:15:58
391間違えました.スレ汚してすいません
template<LHS, RHS>
struct plus_result{
typedef typeof(l + r) type;
private:
LHS l;
RHS r;
};
struct plus
{
template<class LHS, class RHS>
typename plus_result<LHS, RHS>::type operator()(
LHS const &lhs, RHS const &rhs) const
{ return lhs + rhs; }
};
393:デフォルトの名無しさん
05/03/13 18:17:47
typeof って何で標準に入る予定ないの?
394:デフォルトの名無しさん
05/03/13 18:21:14
最初からplus_resultのとこにtypeofを書けばいいような?
395:デフォルトの名無しさん
05/03/13 20:16:10
>>393
そんなこと誰が言ったんだ?
396:デフォルトの名無しさん
05/03/13 22:50:55
条件Aに適合する場合にBを適用するという意味で
apply_if を書いてみたのですが、駄目だしをお願いします。
template <typename IIte, typename CheckPred, typename ApplyPred>
void apply_if(IIte begin, IIte end, CheckPred check, ApplyPred apply)
{
for(;begin!=end;++begin)
{
if(check(*begin)) apply(*begin);
}
}
397:デフォルトの名無しさん
05/03/13 23:18:26
>>396
じゃ遠慮なく。
・名前の省略するな。(×IIte → ○InputIterator)
・Pred は predicate(述語) の略なので、 bool を返す関数以外には使うな。(×ApplyPred → ○UnaryFunction)
・*begin が繰り返されているのは良くない。
・std::for_each() に倣って UnaryFunction を戻り値としたほうがいいかもしれない。
398:デフォルトの名無しさん
05/03/14 00:29:28
>>397
細かいことを言えば、
InputIterator に apply はまずい。
InputOutputIterator じゃ長いけど。
399:デフォルトの名無しさん
05/03/14 01:03:01
とりあえず試しに Visual C++ Toolkit 2003 を使ってみたけど、
typeof() は使えない模様。__typeof とかなんかあったりするのかな?
400:デフォルトの名無しさん
05/03/14 01:06:34
>>398
イテレータのコンセプトを表すという意味で InputOutputIterator はありえない。
出力も兼ねると言うことなら、現行の規格では ForwardIterator が候補になるだろう。
しかしここも std::for_each() に倣って InputIterator とするのが正解だろう。
401:デフォルトの名無しさん
05/03/14 01:13:19
なんなんだよ、typeof()って?
初めて聞いたぞ。
type_infoクラスとtypeid演算子ならC++にあるけど、
typeof()は何をするためのもの?
402:デフォルトの名無しさん
05/03/14 01:21:18
>>401
まず最初に言っておくと、typeofは今のところまだ標準には無い。
で、まぁ名前の如く変数の型を得る演算子(?)の事。
Type a;
typeof(a) b = a;
みたいに使える。
この例では a の型が分かってるけど、Expression Template なんかの場合はどえらい事になっちゃうっしょ。
って分かりにくいかなぁ。誰か分かりやすい例キボンヌ。
403:デフォルトの名無しさん
05/03/14 01:27:44
その程度だとtypeid, type_infoとどう使い方が違うのか見えんな。
404:デフォルトの名無しさん
05/03/14 01:29:18
テンプレート宣言の
template<typename HOGE>
を適宜、
template<typename HOGE, typename PLUS_TYPE>
にすれば回避できるんじゃないの?
曖昧さの解決にもなるし。
というか、C++とtypeof()は相性が最悪な気がする。
多重継承さえ嫌がる人が多いというのに、
typeof()は、無駄にデバッグ作業を増やさせるだけではないか?
405:デフォルトの名無しさん
05/03/14 01:31:35
>>400
ForwardIteratorが正しいね。
しかし、InputIterator で要素の変更を行うのは論外では?
for_each()は変更を伴わない関数。
本質的に違う関数に倣うという理由付けも理解に苦しむ。
406:デフォルトの名無しさん
05/03/14 02:01:52
>>405
std::for_each() で要素の変更は許される方向にあるらしい。
URLリンク(www.open-std.org)
「いまさら禁止されては困る」という本音が多分にあるだろうと思うので、
明示的に許可を後付けされてもすっきりしないよな。
はっきりと Mutating algorithm に移動させて欲しい。
407:デフォルトの名無しさん
05/03/14 08:46:06
>>403
オマエの目は節穴なのでしょうか?
408:402
05/03/14 11:23:16
>>403
うーん、例が悪いでしょうかねぇ。ただ、typeidと決定的に違うのが、
「コンパイルタイムに決まる」、という事。
んだから、「謎の型を宣言、定義可能」って事なんですけどね。
明日から海外飛ぶんで誰かフォローよろ。
409:デフォルトの名無しさん
05/03/14 12:32:23
俺も来週から地方飛ばされるんで
誰か助けてくれ
410:デフォルトの名無しさん
05/03/14 12:37:00
俺はneetなんである意味助けてくれ
411:デフォルトの名無しさん
05/03/14 12:37:50
>>408,409
そのままキャッチされない例外に飛ばされて人生の強制終了。
412:デフォルトの名無しさん
05/03/14 12:43:12
C++よりMLの方がいいよ。
413:デフォルトの名無しさん
05/03/14 12:45:00
メーリングリスト
414:396
05/03/14 23:32:14
>>397,398,400,401,405,406
参考にしたいと思います。ありがとうございます。
415:デフォルトの名無しさん
05/03/15 00:04:29
C++よりMLの方がいいよ。
416:デフォルトの名無しさん
05/03/15 00:16:03
>>412
>>415
利点をあげてくれ、なにがいいのかわからん
417:デフォルトの名無しさん
05/03/15 00:47:28
このスレが不要になるぐらい明快
418:デフォルトの名無しさん
05/03/16 07:47:07
そうか、typeofはgccとintel以外じゃ使えないのか。
クラス階層のメンバを辿るときとか便利なんだよな。
node->get_parent()->get_view() とかで参照をとるとき、一回だけだと
その場に書くけど長いと面倒なので何か別名を割り当てるためだけに
ローカル変数に代入するわけだ。
そういうとき、
#define LET(var,exp) typeof(exp) var = (exp)
とかすると
VeryVeryLongClassName parent_view = node->get_parent()->get_view();
のかわりに
LET(panent_view, node->get_parent()->get_view());
と書ける。非常にラクチン。
boostのlambdaみたいにすればtypeofなしでも同じようなことができるかも。
419:デフォルトの名無しさん
05/03/16 08:08:57
>>418
boost spirit typeof
420:418
05/03/16 09:26:00
どうもboostの定義をみてるとMetrowerksにもtypeofがあるようだ。
んで、typeofのテンプレートによる実装もあるみたいだね。
URLリンク(aspn.activestate.com)
boostのsandboxにtypeofの実装があるらしい
URLリンク(aspn.activestate.com)
Code Projectの記事。typeofのVC7用実装。
これによるとboost::mplにも
BOOST_MPL_AUX_REGISTER_TYPE(123, abc);
abc aa1;
BOOST_MPL_AUX_TYPEOF(_, aa1) *aa2 = &aa1;
というtypeofがあるらしいがundocumentedだのuglyだの不便だのと切って捨てている。
>>419
? よくわからんちん。
421:デフォルトの名無しさん
05/03/16 15:39:09
>>420
URLリンク(boost.cppll.jp)
typeofはレビュー待ちの状態だと以前読んだ希ガス
422:デフォルトの名無しさん
05/03/16 16:23:33
>>420
Metrowerks CodeWarriorでの話。
__typeof__()演算子があって、これは常に使える。typeof()演算子を使うには
#pragma gcc_extensions onとする必要がある。こうすると、以下のGNU Cの言語
拡張機能を利用します。
・auto変数の構造体、または配列を、定数以外の値で初期化することを許可します。
・sizeof( void ) == 1
・sizeof( function-type ) == 1
・評価式の内部のGCCステートメントと宣言を、制限付きでサポートします。
・#undefがその前にないマクロの再定義。
・GCCのtypeofキーワード。
423:デフォルトの名無しさん
05/03/17 09:40:37
>418
>boostのlambdaみたいにすればtypeofなしでも同じようなことができるかも。
逆だと思いますよ.lambdaも状況は似たようなもので
むしろlambdaもtypeofがあればいろいろうれしいです.
でもboostのtypeofの実装はさすがにやりすぎな気が・・・
そもそもtypeofの機能をライブラリで提供する/できるというのが異常というか
424:418
05/03/17 10:10:08
420のCode Projectの方のリンクが寝惚けてました^^; 正しいのはこっち。
URLリンク(www.codeproject.com)
>>421
すいません、あいかわらずよくわかりません。subruleが普通のコードでも使え
るってこと? 数字を手で入れる必要があるのは面倒なような……。
>>422
補足サンクスです。そうそう、__typeof__でした。
そうか、MetrowerksはGCC拡張を一部サポートするんですね。
425:デフォルトの名無しさん
05/03/25 00:52:31
gcc 3.4のバグだろうか。
テンプレート関数の中で
boost::mpl::identity<typeof(foo->get_bar())>::type bar;
と変数を定義しようとすると何故か
expected `;' before "bar"
というエラーになる。
普通の関数の中なら問題なく通るのだけど。
426:デフォルトの名無しさん
05/03/25 00:58:26
>>425 typname
427:デフォルトの名無しさん
05/03/25 02:26:51
>>426
サンクス。
typenameは試したはずなんだけど……と思いつつやってみると
コンパイル通りました。吊ってきます。
428:デフォルトの名無しさん
05/03/30 01:09:51
Boost.Serialization の
#include <boost/serialization/shared_ptr.hpp>
にある
#define private public
#include <boost/shared_ptr.hpp>
#undef private
って、shared_ptr の方を変更してもらえないんですかね?
別のスレッドで Boost.Serialization を教えてもらったんですけど、
これが、ちょっと気になります……。
429:デフォルトの名無しさん
05/03/30 01:17:26
変更して貰えるわけないだろ、氏ね(ここまで一筆書き)
430:428
05/03/30 02:21:20
>>429
Boost 同士ということで friend にしてもらうくらいなら、
と思ったんですが、直接には関係しない物のために変更するのは、
やっぱり無理ですよね。
次ページ最新レス表示スレッドの検索類似スレ一覧話題のニュースおまかせリスト▼オプションを表示暇つぶし2ch
5373日前に更新/262 KB
担当:undef