[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 901- 1001- 2chのread.cgiへ]
Update time : 05/09 22:57 / Filesize : 262 KB / Number-of Response : 1002
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

【C++】template 統合スレ -- Part6



1 名前:デフォルトの名無しさん mailto:sage [04/11/25 21:11:32]
C++ のジェネリックプログラミングの話をしましょう。
以下のスレッドを統合するスレです。
STLスレッド
Part1 pc.2ch.net/tech/kako/1004/10042/1004287394.html
Part2 pc3.2ch.net/tech/kako/1026/10267/1026793823.html

【C++】Boost使い集まれ!
pc3.2ch.net/test/read.cgi/tech/1033830935/ (html化待ち?)

Generic Programming with C++ Template
pc.2ch.net/tech/kako/1008/10085/1008593126.html
【C++】template 統合スレ -- STL/Boost/Loki, etc.
pc2.2ch.net/tech/kako/1037/10377/1037795348.html
【C++】template 統合スレ -- Part2
pc2.2ch.net/test/read.cgi/tech/1047978546/ (html化待ち)
【C++】template 統合スレ -- Part3
pc5.2ch.net/test/read.cgi/tech/1066493064/ (html化待ち)
【C++】template 統合スレ -- Part4
pc5.2ch.net/test/read.cgi/tech/1083550483/ (html化待ち)
【C++】template 統合スレ -- Part5
pc5.2ch.net/test/read.cgi/tech/1091522597/
関連スレ、その他リンクは >>2-5 あたりに。


181 名前:デフォルトの名無しさん mailto:sage [05/01/06 20:30:30]
こういうのどうですか?

#defineBEGIN_JUNK( __Super, __Misc ) \
template< int _N >struct __Junkyard{ enum { _junk_no = __Junkyard< _N - 1 >::_junk_no }; }; \
template<> \
struct __Junkyard< __LINE__ > : public __Super::_junk \
{ \
enum { _junk_no = __LINE__ }; \
typedef __Super::_junk _prev; \
__Misc; \
}; \
typedef__Junkyard< __LINE__ >_start_junk; \

#defineREDEF_JUNK( __Misc ) \
template<> \
struct __Junkyard< __LINE__ > : public _prev_junk \
{ \
enum { _junk_no = __LINE__ }; \
typedef _prev_junk_prev; \
__Misc; \
}; \

#defineEND_JUNK() \
typedef_cur_junk_junk; \

長いので詳細は↓に書いてあります。
www2.odn.ne.jp/freelife/Junkyard.htm

割と使えると思うんだがどうだろう?


182 名前:デフォルトの名無しさん mailto:sage [05/01/06 22:08:44]
>181
マクロで実装してるreflection系ライブラリの提案見るたびに思うんですけれど
マクロとテンプレートの相性の悪さはどう対処するつもりなんでしょうか?
毎回typedef?(面倒)BOOST_PP_SEQ?(カッコ悪い)variadic macro待ち?(いつ出る?)

struct Sample2
{
typedef Sample2 _self;
BEGIN_JUNK( ZJunkBase, typedef ZTypeList<> _data_member1; );
DATA_MEMBER( 1, my_class<char, int>, x );
END_JUNK();
};


183 名前:181 mailto:sage [05/01/06 22:39:57]
>>182
言いたいことには同意
対処って程ではないが、苦肉の策でこんなことやってる

#define $ ,

struct Sample2
{
typedef Sample2 _self;
BEGIN_JUNK( ZJunkBase, typedef ZTypeList<> _data_member1; );
DATA_MEMBER( 1, my_class<char $ int>, x );
END_JUNK();
};

はげしくかっこ悪いが w



184 名前:デフォルトの名無しさん mailto:sage [05/01/06 22:59:24]
>183
それだとDATA_MEMBERが評価される前に$が評価されてしまうので結局同じことになりませんか?

色々漁ってみたら限界はあるもののいくつか対処法はあるみたいですね.
lists.boost.org/MailArchives/boost/msg46364.phpからだと

template<class T> struct wrap { typedef T type; };
template<class T> struct wrap<void (T)> { typedef T type; };
#define TYPE(x) wrap<void x>::type
#define DEP_TYPE(x) typename wrap<void x>::type

struct Sample2
{
typedef Sample2 _self;
BEGIN_JUNK( ZJunkBase, typedef ZTypeList<> _data_member1; );
DATA_MEMBER( 1, TYPE((my_class<char, int>)), x );
END_JUNK();
};

とか.記事本文では指摘されていないですけれど,型がdependent typeか
どうかでマクロを使い分ける必要もありますね,これ.
・・・っていうか話題をそらしてしまってすいませんです.

185 名前:181 mailto:sage [05/01/07 00:10:36]
>>184
コンパイル通らないですか?
当方、VC++ 2003 しかないので、他のコンパイラだと通らないのだったら正直すまん
ただ、VC++ 2003 でも多重にマクロを定義している時は、評価順序によって通らない時もある
その時はマクロを調整するでは駄目ですか・・?

リンク先のようなやり方もあるとは知りませんでした
参考にさせて頂きます




186 名前:181 mailto:sage [05/01/07 00:38:04]
あと、typename に対してですが
__if_exists が使えればこういうやり方もあります

template< bool >struct ExistsBool {};
template<>struct ExistsBool< true > { enum { _true }; };

#defineTYPEDEF( __Type, __Alias ) \
__if_exists( __template__::_true ){ \
typedef typename __Type __Alias; \
} \
__if_not_exists( __template__::_true ){ \
typedef __Type __Alias; \
} \


template< class _Type >
struct Sample7
{
typedef ExistsBool< true >__template__;

TYPEDEF( _Type::_type, _type );

// 2値判定にも使える
__if_exists( ::ExistsBool< _Type::_n == 0 >::_true ){
}
};

__template__ をクラスごとに宣言する必要があるのが難点ですが


187 名前:デフォルトの名無しさん mailto:sage [05/01/07 19:48:15]
>>184
>それだとDATA_MEMBERが評価される前に$が評価されてしまうので結局同じことになりませんか?
引数展開の前に引数は確定するから、この例では問題ない。
でもこの結果を別のマクロに渡すと結局だめだから、
あまりお勧めはできないが。

# define ID(x) x
# define COMMA() ,
# define DECL_A(type, var) type var
# define DECL_B(type, var) ID(type) var

DECL_A(std::pair<int COMMA() int>, pa); // ok
DECL_B(std::pair<int COMMA() int>, pb); // error: IDの引数過多

188 名前:184 mailto:sage [05/01/07 21:39:12]
>186
考えてみた結果enclosing scopeがtemplateかどうかに対する切り分けが
本質的に必要ではないかと思うのでこの方法はあまり使えなさそうです.

>187
マクロのargument substitutionについて理解が足りていませんでした.
function-like macroがidentityされてから後,replacement-listに対する
置換が実行される前にargumentに含まれるmacro tokenが置換されるんですね.
見た感じやはり184の解法が幾分かbetterでしょうか.

189 名前:181 mailto:sage [05/01/08 00:55:07]
これでどうだろう。>>184 と組み合わせてみた。

template<class T> struct wrap{ typedef T type; };
template<class T> struct wrap<void (T)>{ typedef T type; };
#define TYPE(x) wrap<void x>::type

template< bool >struct ExistsBool{};
template<>struct ExistsBool< true >{ enum { _true }; };

#defineTYPEDEF( type, alias ) \
__if_exists( __template__::_true ){ typedef typename TYPE((typename type)) alias; } \
__if_not_exists( __template__::_true ){ typedef TYPE((type)) alias; } \

#defineCLASS( __Class ) \
typedef __Classself; \
typedef ExistsBool< false >__template__; \

#defineTEMPLATE( __Class ) \
typedef __Classself; \
typedef ExistsBool< true >__template__; \

#define$,





190 名前:181 mailto:sage [05/01/08 00:55:32]
つづき

template< class T >
struct hara
{
TEMPLATE( hara );

template< class T > struct horo
{
TEMPLATE( horo );
TYPEDEF( T::type,type );
};
struct hire : public horo< T >
{
CLASS( hire );
TYPEDEF( my_class<char $ int>, type2 );
};

TYPEDEF( hire::type, type );
TYPEDEF( hire::type2, type2 );
};

$ を主張するわけではないが、タイプ量が少ないと嬉しいので
ところで、誰も Jankyard に触れてくれない orz


191 名前:デフォルトの名無しさん mailto:sage [05/01/08 01:04:10]
誤: typedef __Classself;
正: typedef __Class self;
誤: #define$,
正: #define $ ,

です。連投すんまそん


192 名前:デフォルトの名無しさん mailto:sage [05/01/09 07:22:01]
>ところで、誰も Jankyard に触れてくれない orz
ぶっちゃけていうとreflection系ライブラリの提案はすでに色々ありますからね.
自分の知っている範囲だと
www.garret.ru/~knizhnik/cppreflection/docs/reflect.html
www.arneadams.com/reflection_doku/index.html
あたりでしょうか?後プロパティの実装なら
www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1615.pdf
とか.
ついでに__if_existsに関して,名前がするかどうかというコンパイル時の情報で
プリプロセッサレベルの処理を行えるというのは確かに強力で魅力的なんですが
やはりVC++限定なのがネックでしょうね.
一応クラスのメンバ(型・関数・変数)や非メンバ関数の存在をテストしてその情報を
コンパイル時に取得する技法を標準C++の範囲内で実装することは可能なので,
それでほとんどの部分は代用できると思います.
(というか自分は本質的に__if_existsが必要な状況を思い付けません)

193 名前:181 mailto:sage [05/01/09 09:15:49]
>>192
今回提案したのはリフレクション自体ではなく、その辺りをサポートする仕組みだったのだが。
リフレクションも含む、その他タイプリスト生成や、マクロ間での型の受け渡し、
継承関係の中で連番発行など。プロパティはネタです。

__if_exists は本質的に必要ないのには同意します。
ただ、テンプレートの特化の変わりに使えるので
__if_exists を使うとシンプルに記述出来ることも少なくありません。
この辺りは好みによるのでしょうね。
VC++限定なのはどうしようもないですが。

いづれにせよ、騒がしているだけのようなので、これで引っ込むことにします。

>一応クラスのメンバ(型・関数・変数)や非メンバ関数の存在をテストしてその情報を
>コンパイル時に取得する技法を標準C++の範囲内で実装することは可能なので,
>それでほとんどの部分は代用できると思います.
詳細きぼん


194 名前:デフォルトの名無しさん [05/01/09 12:47:08]
ここでいいのかしら。ちょっと彷徨い気味ですがどうぞよろしゅう

2つのソート済みvectorの中で共通する項目の数を数えたいのですが
set_intersection( (省略) , common_ins)
common.size();
で実行しています。これだとvectorの中身が100kとかになった時に速度がちょっとまずいのです。
上記より高速な方法でなにか良案ご存知の方いらっしゃいませんか?
ちなみのその後、共通部分から作ったcommonに対する処理は何も行いません(数えたいだけです)

195 名前:デフォルトの名無しさん mailto:sage [05/01/09 12:52:27]
vecAとvecBを
mergeしてvecCを作りuniqueしてvecA.size()+vecB.size()-vecC.size()

196 名前:デフォルトの名無しさん mailto:sage [05/01/09 12:54:20]
set_intersectionもソート済み範囲なのか。なら>>194の方が遅そうだ。

197 名前:デフォルトの名無しさん mailto:sage [05/01/09 12:59:38]
>>195のがだろ

198 名前:デフォルトの名無しさん mailto:sage [05/01/09 13:00:07]
www.google.com/search?num=100&as_qdr=all&as_occt=any&as_dt=i&ie=sjis&oe=sjis&lr=lang_ja&as_q=%83%5c%81%5b%83g%8d%cf%82%dd%83x%83N%83%5e%82%cd%92x%82%a2

199 名前:194 mailto:sage [05/01/09 13:14:44]
mergeして差分を考える方法は実行済みなのですが
残念ながら、set_intersectionの方法に比べて倍近く時間がかかってしまったのです

う〜ん、これはもう構造的にどうしようもないですかね
割と頻繁に更新されるvectorなので、馬鹿にならないコストなんですが・・・



200 名前:デフォルトの名無しさん mailto:sage [05/01/09 13:29:34]
スマートポインタを使ってるならただのポインタに変えてみる。
ただのポインタなら実体に変えてみる。
実体ならポインタに変えてみる。

201 名前:デフォルトの名無しさん mailto:sage [05/01/09 13:33:31]
set_intersection の result は OutputIterator なので、
 *result = common (or *result++ = common)
がカウントアップの動作をするような擬似イテレータを作れば、
コピーのコストを無くすことができそうだ。

202 名前:デフォルトの名無しさん mailto:sage [05/01/09 13:39:05]
うっ、そこを触ることになりますか…
Iteratorの中身について理解が出来ていないので全くの手探りになりますが、資料ひっくり返して勉強します
ありがとうございました

203 名前:デフォルトの名無しさん mailto:sage [05/01/09 14:48:42]
暇つぶしにやってみた。
boost::counting_iterator がそのまま使えるかと思ったけど OutputIterator じゃなかった。
しょうがないから結局ファンクタ書く羽目になった。

#include <cstddef>
#include <algorithm>
#include "boost/function_output_iterator.hpp"

template<typename Incrementable>
class increment
{
  Incrementable* m_target; // not reference to make this class Assignable
public:
  increment(Incrementable& target) : m_target(&target) {}
  template<typename T> void operator () (T const&) { ++*m_target; }
};

template<typename InputIterator1, typename InputIterator2>
std::size_t count_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
{
  std::size_t result = 0;
  std::set_intersection(first1, last1, first2, last2
    , boost::make_function_output_iterator(increment<std::size_t>(result)));
  return result;
}

lambda 使えば、 increment くらい消せるかも。

204 名前:デフォルトの名無しさん mailto:sage [05/01/09 17:29:22]
いちおうできた。

#include <cstddef>
#include <algorithm>
#include "boost/function_output_iterator.hpp"
#include "boost/lambda/lambda.hpp"

template<typename InputIterator1, typename InputIterator2>
std::size_t count_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
{
  std::size_t result = 0;
  std::set_intersection(first1, last1, first2, last2
    , boost::make_function_output_iterator(++boost::lambda::var(result)));
  return result;
}

ただ、 lambda のファンクタが Assignable にならないので、
_GLIBCXX_CONCEPT_CHECKS で怒られた。
VCでは /W3 まで大丈夫。

205 名前:デフォルトの名無しさん [05/01/09 19:25:21]
template<class T>
struct X {
void func() {}
};

TがクラスAかクラスAのpublic派生クラスの特殊版を定義する場合
X<T>::func()をどのように定義すればよいのでしょうか?


206 名前:デフォルトの名無しさん mailto:sage [05/01/09 23:59:37]
>193
具体的な実装の例だとboost/mpl/has_xxx.hppとかが参考になるかと思います.

>205
Boost使うなら以下のような感じでですかね?

#include <iostream>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
struct A{ };
template<class T> struct X{
struct yes_tag{ };
struct no_tag{ };
typedef typename boost::mpl::if_<
boost::is_base_and_derived<A, T>, yes_tag, no_tag>::type
dispatch_tag;
void func_dispatch(yes_tag){std::cout << "derived version" << std::endl;}
void func_dispatch(no_tag){std::cout << "non-derived version" << std::endl;}
void func(){ func_dispatch(dispatch_tag()); }
};
struct Hoge : public A{ };
struct Huga{ };
int main(){
X<Hoge>().func();
X<Huga>().func();
}

207 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:24:10]
こういう書き方って動作は保証されるのでしょうか?

std::vector<int> test;

for ( std::vector<int>:iterator element = test.begin(); element != test.end(); element++ ) {
test.erase(element);
}


208 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:30:51]
↑おもいっきりぬけてたので修正しました

std::vector<int> test;

test.push_back(0);
test.push_back(1);
test.push_back(2);
test.push_back(3);
test.push_back(4);


for ( std::vector<int>:iterator element = test.begin(); element != test.end(); element++ ) {
if ( *element == 2 ) {
test.erase(element);
}
}


209 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:35:21]
>>208
eraseした時点でイテレータそのものが無効になるよ。



210 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:38:08]
ではループしつつ条件に当てはまるイテレータの内容だけ削除するには
どのような手段を用いればよいのでしょうか?
プールで一端どこかにマークをつけて、ループ終了後該当の物だけeraseとかでしょうか?

211 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:38:33]
だから、std::remove()で、値が2の要素をコンテナの後に集めておき、最後に一回だけ
eraseするといい。

test.erase(std::remove_if(test.begin(), test.end(), std::bind2nd(std::equal<int>(), 2)), test.end());

212 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:38:57]
あ、ループがプールに・・orz

213 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:39:57]
なるほど、ありがとうございます

214 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:40:36]
こういう書き方は最初は戸惑うかもしれないが、慣れるとすごく便利になる。
そのうちこれでも不便になって、必ずboost::bindとかに手を出したくなるから。

215 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:43:26]
わかりました。
参考にしてみます。

216 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:43:57]
というか、EffectiveSTLを読め。
>>211のも含めて色々書いてあるから

217 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:50:47]
test.erase(std::remove(test.begin(), test.end(), 2), test.end());
でもいいねこの場合。叙述関数あるいは関数オブジェクトの替わりにconstな値を
とるだけだから。

218 名前:デフォルトの名無しさん mailto:sage [05/01/10 17:58:23]
if ( *element == 2 ) {
test.erase(element++);
}

でOK。

219 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:01:18]
>>218は忘れて。

for ( std::vector<int>:iterator element = test.begin(); element != test.end(); ) {
if ( *element == 2 ) {
element = test.erase(element);
}
else
++element;
}



220 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:01:28]
>test.erase(std::remove_if(test.begin(), test.end(), std::bind2nd(std::equal<int>(), 2)), test.end());

わけがわかりません。
こんなの仕事で使われたら恐怖です。
やめてください。


221 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:02:08]
>>217-219
やめてください。
怖いです。

222 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:02:50]
>>218
vectorコンテナのeraseはCで言うところのrealloc()に相当する動作を実行する
事もあるんだぞ。でたらめ書くな。

223 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:03:47]
>>220
そのくらいのSTL構文も分からないならC++使うのをやめた方がいいよ。

224 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:06:37]
>>222
おいおい。
「イテレータは、より小さなインデックスの要素が挿入または削除されたり、再割り当てが
行われて容量が変わるまで有効」だぞ。
規格票をよく読め。おまえこそでたらめ。

225 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:10:44]
規格票でました。

m9(^Д^)プギャー

226 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:12:25]
§23.1.2.8当たりだろ。

227 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:13:13]
www-6.ibm.com/jp/developerworks/linux/041203/j_l-cpregex.html
>言語の機能 であるはずのものが、その言語のユーザーを恐れさせるようになったら、何かを変えるべき時なのです。


228 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:13:59]
>>226
それAssociative Container

229 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:15:05]
ここは
問題を無闇に複雑にして悦に浸る馬鹿のス靴(なぜか変換できない)
ですね。



230 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:19:30]
§23.2.4.3当たりだと見た。

231 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:20:25]
>>227>>229
またperlとかrubyの○キ信者ですか?

232 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:23:27]
boostが異常なのは認めなければなるまい。
昨今のC++は異常が常態。

233 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:24:29]
確かに異常だが、使っているうちに快感になる。

234 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:24:50]
(23.1.1/7)と(23.2.4.3/3)読む限り>219でもOKっぽいですね

235 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:27:46]
CommonLispのようなわかりにくさを競い合って悦に浸るのがここの流儀

236 名前:デフォルトの名無しさん mailto:sage [05/01/10 18:28:39]
>>234
OKだろ。個人的には俺はあまり書きたくないけど。

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 名前:デフォルトの名無しさん mailto:sage [05/01/11 01:06:22]
>>237 ダメ



240 名前:デフォルトの名無しさん mailto:sage [05/01/11 14:28:58]
for(element = test.begin(); element != test.end(); ++element)
if(*element == 2)
{
element = --test.erase(element);
}
こんな感じが一番シンプルなところなのかな?

241 名前:デフォルトの名無しさん mailto:sage [05/01/11 15:04:23]
removeとeraseの組み合わせが一番シンプル

242 名前:デフォルトの名無しさん mailto:sage [05/01/11 15:59:47]
とりあえずremoveとeraseの組み合わせが何でも一番です(^^


243 名前:デフォルトの名無しさん mailto:sage [05/01/11 16:01:18]
clearって手もあるよ

244 名前:デフォルトの名無しさん mailto:sage [05/01/11 19:46:02]
>>223
プロジェクトって大抵いろんな技術レベルの人がいるから
その台詞でばっさりはちょっと抵抗あるなぁ。
一人でやるなら何使ったってOKだけどね。

245 名前:デフォルトの名無しさん mailto:sage [05/01/11 20:32:55]
>>244
211はかなり基本だと思うんだけど...


246 名前:デフォルトの名無しさん mailto:sage [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 mailto:sage [05/01/12 01:12:53]
>>245
俺も基本だと思ってるし、これぐらいわかれよって思ってるよ。
でも、それが通用しないのが多人数でしょ?って投げかけ。
…技術と関係なくなるか。消えるよ。スレ汚しすまん。



250 名前:デフォルトの名無しさん mailto:sage [05/01/12 02:17:30]
なぜforで回す……わざわざC++使うんだったら、効率にも気を
配らないともったいないよ。

>247
>237 >240の例だと
・ループごとにtest.end()の呼び出しが発生する
・elementを削除するたびにvectorの再パッケージが発生する
で遅くなりますな。

あと、>237だと後置インクリメントの一時オブジェクトの生成が
発生してさらに効率が悪くなります。


251 名前:デフォルトの名無しさん mailto:sage [05/01/12 02:18:18]
なぜにremoveを使いたくないのかが知りたい

252 名前:250 mailto:sage [05/01/12 02:24:13]
自己フォロー

>237>240ともに、はelement==test.begin()のときに
*element==2だとアウトですな。

#test.begin()よりも前に移動するから未定義の世界に突入


253 名前:デフォルトの名無しさん mailto:sage [05/01/12 02:48:28]
>250
ループごとのtest.end()も後置インクリメントもここでは本質じゃない。

254 名前:デフォルトの名無しさん mailto:sage [05/01/12 02:56:25]
>253
ふうん、じゃ、こう言っておこうかな
・郷に入れば郷に従え
STLはC++の一部なんだから、それぐらい覚えろ
・こんぐらいできないなら、そもそもC++使うな
or こんなこともできないやつをプロジェクトに入れるな

他にもPerlとか色々あるんだから、わざわざC++を使う必要ないよね。


255 名前:デフォルトの名無しさん mailto:sage [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 mailto:sage [05/01/12 07:50:40]
s/Container/Sequence/

remove() の意味が混乱を招きやすいという認識はSGIのドキュメントにも記載されている。
「慣用句だ」と言って押し切るよりは、むしろまともな認識だと思う。
www.sgi.com/tech/stl/remove_if.html#1

これをそのままソースに書いてしまうと言うのは、
例えば定数除算をシフトで書いてしまうのと同等の誤りであると思う。

257 名前:デフォルトの名無しさん [05/01/12 07:51:49]

forで回すからうっかり>>218とか>>237とか>>240とかいう問題のあるコードを書いて
しまうんだよ。
だったらおとなしくremoveを使えと。

まぁ、色々書き方があってその中から適切な物を状況に応じて選ぶのがプログラムの
醍醐味ではあるけど。


258 名前:デフォルトの名無しさん mailto:sage [05/01/12 08:53:47]
>なぜにremoveを使いたくないのかが知りたい
叙述関数やoperator==とかにコードが分散するのがイヤ
ループが内包されるのがイヤ ループを制御下に置いておきたい
ブレイクポイントが設定しやすいよ
削除以外の用途にループが流用できるよ

てゆうかぶっちゃけremove_copy中でやってること、あれはありえないでしょ
それを言ったらvectorでeraseすること自体ありえないかw

259 名前:デフォルトの名無しさん mailto:sage [05/01/12 09:59:55]
>ループが内包されるのがイヤ ループを制御下に置いておきたい

ループを明示的に書くより効率が良くなる可能性があるし、
コードの見通しも良くなる



260 名前:デフォルトの名無しさん [05/01/12 10:06:05]
>>254
「理想郷」との差でしかモノを語れない
頭でっかちの引き籠もりはレスしなくていいです ;-)

261 名前:デフォルトの名無しさん mailto:sage [05/01/12 10:32:21]
>260
それ、オレじゃない。人違いだ

262 名前:デフォルトの名無しさん [05/01/12 10:48:33]
>260
IDくらい見ろ、ボケ!

263 名前:デフォルトの名無しさん mailto:sage [05/01/12 11:10:58]
>>262
この板ID無いんだって気付よ!

264 名前:デフォルトの名無しさん mailto:sage [05/01/12 11:21:54]
お前さんたちなんか楽しそうだね。

265 名前:デフォルトの名無しさん mailto:sage [05/01/12 11:42:25]
IDの見方知らない香具師ってまだいたんだね

266 名前:デフォルトの名無しさん mailto:sage [05/01/12 12:13:29]
はっきりいってvectorに限らず配列っぽいデータ構造を使っている時に
removeみたいなアルゴリズムを適用したくなることってあるか?
無理して適用しておもしろいことがあるようなものでもないと思うのだけど…
何か見落としている革新的な理由でもあったりするのだろうか?

267 名前:デフォルトの名無しさん mailto:sage [05/01/12 23:55:01]
> removeみたいなアルゴリズムを適用したくなることってあるか?

配列から複数の要素を一度に取り除きたいときだな。


268 名前:デフォルトの名無しさん mailto:sage [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 名前:デフォルトの名無しさん mailto:sage [05/01/17 09:41:54 ]
俺も小さくて、しかもあまり使わないような関数を分散させるのが嫌いなんだけど、
「リファクタリング」を読むと、一行処理すら場合によっては関数にすることを推奨してるんだよな。

しっかりした関数名をつけることによって可読性が高まるって話なんだけど、
必ずしもそうとは思えないのは、英語圏ネイティブじゃないせいかね。

と、templateスレに書き込もうとしたのだけど、主旨に合わないのでこっちに投棄

272 名前:デフォルトの名無しさん mailto:sage [05/01/17 09:43:01 ]
C++スレに書くつもりが…
もうどうでもいいや

273 名前:デフォルトの名無しさん mailto:sage [05/01/17 13:41:34 ]
リファ〜に書いてあるのは関数じゃなくてメソッドのことでは
何の分類もしない単独の関数増やしてくのはあんま良いとは思えないが
メソッドの場合インターフェース抽出とか階層整理とかで意味がある

274 名前:272 mailto:sage [05/01/17 17:58:06 ]
>>273
失礼、つい関数と呼んじまう。
インターフェース抽出や階層整理は、それ自体をメインにして行うべきな気がするんだよねぇ。

それどころかそれ以前で、非道い話だが「たくさんの、たった数行のメソッド」ってだけで、嫌悪感を感じてしまう。

いずれにせよスレ違い申し訳ない。

275 名前:デフォルトの名無しさん mailto:sage [05/01/18 00:41:35 ]
>>273
そんな区別ないだろ。
少なくともC++ではthisポインタの有無しか違いはないわけで、
それが関数分けの基準に影響するとは思えない。

276 名前:デフォルトの名無しさん mailto:sage [05/01/18 01:35:22 ]
時々272のような人いるよね。
読むときあっちこっちの関数みないといけないから、とか言って。

このヘタレが

277 名前:デフォルトの名無しさん mailto:sage [05/01/18 01:45:39 ]
そもそも行数とか関係ないだろ

278 名前:デフォルトの名無しさん mailto:sage [05/01/18 02:41:33 ]
>275
その他にも可視性とアクセス範囲に違いがあるわけで……


279 名前:デフォルトの名無しさん mailto:sage [05/01/18 08:17:20 ]
>>278
そうだな。

それらが要るならクラス作ってメンバ関数を作ればいいし、
要らないならフリー関数にしてもいい。
どう整理するかどうかが違うだけで、
処理に名前をつけてまとめたほうがよいかどうかの基準には関係ない。
複数のフリー関数を作った後に、さらに
それらをまとめてクラスを作ればよいことに気付くことも考えられる。

思い立ったらさっさと名前付けてまとめれ。
渋る意味がわからん。



280 名前:272 mailto:sage [05/01/18 08:20:53 ]
ちとスレ違い悪いんでこっちでレス
pc5.2ch.net/test/read.cgi/tech/1099112338/41

281 名前:デフォルトの名無しさん mailto:sage [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 では普通に通る。







[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<262KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef