【C++】template 統合スレ -- Part6at TECH
【C++】template 統合スレ -- Part6 - 暇つぶし2ch175:デフォルトの名無しさん
05/01/06 10:56:57
何の要件もなしに「重い」と言って切り捨てる >173 も、
何の前提もなしに「致命的なほど遅くはなんねぇ」という >174 も、
同じ程度に浅はかである。

176:デフォルトの名無しさん
05/01/06 11:01:20
>>175
それを否定してしまったら何もかけなくなっちゃうよ。

177:デフォルトの名無しさん
05/01/06 11:09:22
>>176
175が何を否定してるんだ?

178:デフォルトの名無しさん
05/01/06 11:10:18
日本の将来

179:電波系赤の他人
05/01/06 11:13:22
俺も人格も否定しているような気がする。

180:デフォルトの名無しさん
05/01/06 18:37:00
>>172
嫌というほどでもないんですが、
コンパイルが遅そうとか、その程度です

const my_shared_ptr<T> get_obj_ptr() const;
my_shared_ptr<T> get_obj_ptr();

より、

shared_ptr<T const> get_obj_ptr() const;
shared_ptr<T> get_obj_ptr();

の方が意味的に適切だとは思うんですが

自分で書くのめんどうなので、とりあえずboost::shared_ptrでいいや・・・

181:デフォルトの名無しさん
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; \

長いので詳細は↓に書いてあります。
URLリンク(www2.odn.ne.jp)

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


182:デフォルトの名無しさん
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
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:デフォルトの名無しさん
05/01/06 22:59:24
>183
それだとDATA_MEMBERが評価される前に$が評価されてしまうので結局同じことになりませんか?

色々漁ってみたら限界はあるもののいくつか対処法はあるみたいですね.
URLリンク(lists.boost.org)からだと

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

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




186:181
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:デフォルトの名無しさん
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
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
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
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:デフォルトの名無しさん
05/01/08 01:04:10
誤: typedef __Classself;
正: typedef __Class self;
誤: #define$,
正: #define $ ,

です。連投すんまそん


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

193:181
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:デフォルトの名無しさん
05/01/09 12:52:27
vecAとvecBを
mergeしてvecCを作りuniqueしてvecA.size()+vecB.size()-vecC.size()

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

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

198:デフォルトの名無しさん
05/01/09 13:00:07
URLリンク(www.google.com)

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

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

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

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

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

203:デフォルトの名無しさん
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:デフォルトの名無しさん
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:デフォルトの名無しさん
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:デフォルトの名無しさん
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:デフォルトの名無しさん
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:デフォルトの名無しさん
05/01/10 17:35:21
>>208
eraseした時点でイテレータそのものが無効になるよ。

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

211:デフォルトの名無しさん
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:デフォルトの名無しさん
05/01/10 17:38:57
あ、ループがプールに・・orz

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

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

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

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

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

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

でOK。

219:デフォルトの名無しさん
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:デフォルトの名無しさん
05/01/10 18:01:28
>test.erase(std::remove_if(test.begin(), test.end(), std::bind2nd(std::equal<int>(), 2)), test.end());

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


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

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

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

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

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

m9(^Д^)プギャー

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

227:デフォルトの名無しさん
05/01/10 18:13:13
URLリンク(www-6.ibm.com)
>言語の機能 であるはずのものが、その言語のユーザーを恐れさせるようになったら、何かを変えるべき時なのです。


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

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

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

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

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

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

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

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

236:デフォルトの名無しさん
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:デフォルトの名無しさん
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 にしてもらうくらいなら、
と思ったんですが、直接には関係しない物のために変更するのは、
やっぱり無理ですよね。

431:デフォルトの名無しさん
05/03/30 04:00:47
そういうのはここで訊くよりboostのメーリングリストを検索した方がいいのでは。


432:428
05/03/30 05:05:42
>>431
読んでも分からなさそうと言う事で避けてました。すみません。

で、検索してみたら、そのままの議論がありました。
が、やっぱり分かりませんでした。orz

ただ使うだけにします。ありがとうございました。

433:デフォルトの名無しさん
05/03/30 05:40:36
そういう場合はスレッドのURLとか貼っておくといいかもね。

434:デフォルトの名無しさん
05/03/30 13:22:32
Serializetionがオブジェクトを覗き見しなきゃいけないことを>>428は理解してないのか?
shared_ptrの方で変えたら、通常利用で保護出来ないじゃないか。

435:デフォルトの名無しさん
05/03/30 13:57:46
>>434
>>430

436:ヽ(´ー`)ノ ◆.ogCuANUcE
05/03/30 18:14:32
これかな?
URLリンク(lists.boost.org)


437:428
05/03/31 11:07:00
>>436
それです。
shared_ptr の人も交えて、実装に立ち入った問題点などが議論されていて、
日頃使っているだけの私では、良く分かりませんでした。

438:ヽ(´ー`)ノ ◆.ogCuANUcE
int 2ch =05/04/01(金) 20:35:21
>>437
つか、Thread Index で変なとこに飛ばされて、
議論が追っかけずらいんだよね(´・ω・`)


439:デフォルトの名無しさん
int 2ch =05/04/01(金) 23:10:42
>>438
URLリンク(thread.gmane.org)

440:デフォルトの名無しさん
05/04/10 19:16:42
Spiritのアクションってなんで2引数必要なの?
値を代入したい時は冗長になるぅ...

expr = (str_p(L"1"))[boost::lambda::_1,boost::lambda::_2,data=1];


441:デフォルトの名無しさん
05/04/12 10:09:35
template<class T> class A
{
public:
A(const A&); // 引数
A func() // 返り値
{
A a; // 自動変数
return a;
}
};

クラステンプレートで上記のコメントのところのように
Aとだけ書いた場合A<T>と同じ意味になる、という解釈は正しいですか?

442:デフォルトの名無しさん
05/04/12 10:39:06
>>441
正しいです。
URLリンク(www.kuzbass.ru)

443:441
05/04/12 11:09:04
>>442
ありがとう。よくわかりました。

444:デフォルトの名無しさん
05/04/22 04:23:40
鬼車みたいに
マルチバイトで正規表現使えると速度面では有利なのかな?

ワイド文字で
System.Text.RegularExpressions(C#)
boost::wregex
boost::expressive
boost::spirit
試してみたけど敵わなかった...

鬼車>>C#>=boost::wregex>>expressive>>>>>>spirit


445:444
05/04/22 04:52:13
>>444
spiritのパーサの型がわからんかったんで
毎回生成してたは...道理で遅いはずや...
typeid(parser).name()で出力された型にparser保存してループ回したら
鬼車=spiritになったわ...
逝ってくる...


446:デフォルトの名無しさん
05/04/22 21:22:11
CommonLispの正規表現が最速

447:デフォルトの名無しさん
05/04/22 23:32:46
>>445
当たり前だ。C++が遅かったら、コンパイラ言語を使って正規表現を扱う意味が
ないやんけ。

448:デフォルトの名無しさん
05/04/23 01:11:14
コンパイラ言語?
式テンプレートを使ったメタプログラミングのこと?

449:デフォルトの名無しさん
05/04/23 09:45:54
インタプリタ言語と比較してるだけっしょ

450:デフォルトの名無しさん
05/04/23 10:03:21
またなんかミクロな揚げ足取りしてるんだろうね、きっとw

451:デフォルトの名無しさん
05/04/23 10:19:30
>>448
友達いないでしょ。

452:デフォルトの名無しさん
05/04/23 10:23:08
>>448
どういう風に表現すれば一番適切なのか教えて。

>>450-451
おまえらはどうでも良い。

453:デフォルトの名無しさん
05/04/23 10:31:09
言い負けるのが余程悔しいんだろうな。
リアルな世界では気の強さが災いして、友達どころか彼女もいないと思われる。
家族にも総スカン。

454:デフォルトの名無しさん
05/04/23 10:32:56
>>453
どうしてそういう返事をつけるのかな?
普段よっぽど抑圧されてるのか? もっと自分を愛そうね。

455:デフォルトの名無しさん
05/04/23 10:36:57
スレタイ嫁

456:デフォルトの名無しさん
05/04/23 10:51:39
>>447は、C++のコードをコンパイルして実行から速いと言っているのか、
汎用のDFSマシンじゃなくて、式テンプレートを使ったメタプログラミングで、
専用レクサーを生成して実行しているから速いと言っているのか、
どっちなんだ? 両方か?

457:デフォルトの名無しさん
05/04/23 17:26:58
>>456
真性のアフォ?

458:デフォルトの名無しさん
05/04/24 04:51:27
GCC 4.0.0 に TR1 が来ましたね。うれしい。
ソースは boost のごちゃごちゃしたコンパイラ分岐が無くなった分、
だいぶすっきりした印象

459:445
05/04/24 10:46:47
spiritの型導出のためにファイル登録型のtypeof作ってみた。
#pragma once

#include<fstream>
#include<string>
#include<typeinfo>

template <typename T> struct id_of{enum {val=1};};
template <int N> struct id_to_type{};
template <> struct id_to_type<1>{};
#include"type_id_dynamic_impl.h"//(初回は空ファイルを用意)

template<typename T> struct sized { char size[id_of<T>::val]; };
template<typename T> sized<T> obj_class_id_helper(const T&);
#define obj_class_id(x) sizeof(obj_class_id_helper(x).size)
#define typeof(x) id_to_type<obj_class_id(x)>::type

460:445
05/04/24 10:47:24
template<typename T> static void make_typeof(const T&,int ID)
{
std::string class_name = (std::string)(typeid(T).name());
for(int i=0;i<class_name.length();i++){
if(class_name[i]==':')class_name[i]=';';
else if(class_name[i]=='<')class_name[i]='(';
else if(class_name[i]=='>')class_name[i]=')';
}
std::string include_filename = "type_id_dynamic_impl_"+class_name+".h";
std::string include_file = "#include\""+include_filename+"\"";
std::fstream fo_d( "type_id_dynamic_impl.h" );
std::string buf;bool check=false;std::istream si(fo_d.rdbuf());
while(std::getline(si,buf))
if( buf==include_file )
check = true;
if(!check)
fo_d << include_file << std::endl;
fo_d.close();
std::ofstream fo( include_filename.c_str() );
fo <<"#pragma once" << std::endl;
fo << "template <> struct id_of< " << typeid(T).name() << " > { enum{ val = " << ID << " }; };" << std::endl;
fo << "template <> struct id_to_type< " << ID << " >{ typedef " << typeid(T).name() << " type; };" << std::endl;
fo.close();
}

461:445
05/04/24 10:49:54
int main()
{
int a=100;
make_typeof(a,1212);//初回に必要
typeof(a) aa=100;//make_typeof実行後に有効
}


462:デフォルトの名無しさん
05/04/25 22:32:41
これってtypeofを使う前にmake_typeofを書いた実行ファイルを走らせないといけないですよね?
実用上かなり使いにくくないですか?

463:445
05/04/26 00:50:17
>>462
それは承知の上、自動で登録できる代償だと思ってる。
でも、type_id_dynamic_impl.hを書き換えるだけにすべきだろうな...
(ファイル大量発生とMAX_PATH超えちゃう問題あるだろうし)
登録してない場合はこんな感じでコード切り替えりゃ済む問題だし、
常用できないという点には同意。
#if if_exist_typeof(a)
typeof(a) aa=100;
#else
make_typeof(a,1212);
#endif


464:デフォルトの名無しさん
05/04/26 00:53:50
BOOST_TYPEOF_REGISTER_TEMPLATEは飾りなんです
偉い人にはそれがわからんのです

465:Lispのマクロテンプレート
05/04/26 01:04:31
俺の話を聴け~♪
五分だけでいい~♪


466:デフォルトの名無しさん
05/05/07 00:44:34
俺しかいない羊羹マン

467:デフォルトの名無しさん
05/05/07 00:47:41
ノシ

468:デフォルトの名無しさん
05/05/08 12:54:43
質問です。
以下の要件を満たす型に対するtemplate class の
特別バージョンを作ろうと考えています。
・任意のContainer
・Container::value_typeがstd::pair
・Container::value_type::first_typeがint
・Container::value_type::second_typeは任意

例えば以下のようなものです。
std::vector<std::pair<int, int> >
std::deque<std::pair<int, char*> >
std::map<int, std::string>

これを実現するのに、どういった記述を行えばよいのでしょうか?

template<typename T> // これが一般の型を対象としたtemplate class である場合
class A {
//...
};

template<typename T, typename U> // ここらの書式は?
class A { // ここは?
// ?????....
};

よろしくお願いします。


469:デフォルトの名無しさん
05/05/08 13:28:55
>>468
↓で map_with_string 以外は成功するみたい。(@ g++ 3.4.1)
そう簡単じゃないな。

#include <utility>

template< typename T >
struct A
{ static bool const is_specialized = false; };

template< template< typename > class ContainerTemplate , typename PairSecond >
struct A< ContainerTemplate< std::pair< int , PairSecond > > >
{ static bool const is_specialized = true; };

#include <vector>
#include <deque>
#include <map>
#include <string>

#include "boost/static_assert.hpp"

typedef std::vector<std::pair<int, int> > vector_with_int;
typedef std::deque<std::pair<int, char*> > deque_with_pchar;
typedef std::map<int, std::string> map_with_string;

BOOST_STATIC_ASSERT( A< vector_with_int >::is_specialized );
BOOST_STATIC_ASSERT( A< deque_with_pchar >::is_specialized );
BOOST_STATIC_ASSERT( A< map_with_string >::is_specialized );

470:468
05/05/08 14:04:40
ありがとうございます。なんか凄い構文ですね…
vector,dequeとmapの特別バージョンを一緒に出来ない件に関しては、
以下のような感じでごまかすことにします。

template <typename T>
struct Base {
// implementation
static bool const is_specialized = true;
};

template < template <typename> class ContainerTemplate,
typename PairSecond>
struct A<ContainerTemplate<std::pair<int, PairSecond> > >
: public Base<A<ContainerTemplate<std::pair<int, PairSecond> > > > {
};

template < template <typename, typename> class ContainerTemplate,
typename PairSecond>
struct A<ContainerTemplate<int, PairSecond> >
: public Base <A<ContainerTemplate<int, PairSecond> > > {
};

471:468
05/05/08 14:56:37
すみません、訂正です。
: public Base<ContainerTemplate<std::pair<int, PairSecond> > >
: public Base<ContainerTemplate<int, PairSecond> >
でした。

472:デフォルトの名無しさん
05/05/08 22:00:30
std::vector<int, MyAlloc>なんかが、特殊化される悪寒w

473:デフォルトの名無しさん
05/05/09 11:32:52
std名前空間のものを
std名前空間のもので特殊化ないし部分特殊化するのは
可能だがやっちゃダメ

474:デフォルトの名無しさん
05/05/09 12:36:59
>>472
MyAlloc どころか普通の std::vector<int> も特殊化される罠

>>473
この場合、特殊化してるのは vector/deque/map じゃなくて
A のほうだから問題ないんじゃないかと思うんだが

475:468
05/05/09 13:06:57
Baseで typedef typename T::value_type::first_type first_type
とか、諸々のstatic_assert置いておけばなんとかなると踏んでたんですが、
やっぱ変でしたかねぇ。


476:468
05/05/09 13:22:32
たびたびすみません、これだとA<std::vector<int> >が作れないや。
勉強して出直します。


477:473
05/05/09 16:30:48
>>474
あ、>>468のvector,deque等の例に対して言ったんです。

478:468
05/05/09 17:44:25
>>473
468では、Aに渡す型の例としてvector,dequeをあげたのであって、
vector,dequeの特別バージョンを作ることを意図したわけではないのです。


479:デフォルトの名無しさん
05/05/09 18:19:20
>468
ユーザ定義型が絡む場合ならば,std::vector等のstd名前空間内のテンプレートを
特殊化することは許されているんですけれどね.

そもそも468は恐らくソート済みシーケンスとstd::mapを汎用に扱おうとする意図だと
思いますけれど,これらは各種メンバ関数の宣言その他もろもろからして違うので
汎用に扱おうとするのはかなり無理がないですか?

480:468
05/05/09 18:44:11
何度もすみません。
>そもそも468は恐らくソート済みシーケンスとstd::mapを汎用に扱おうとする意図だと
>思いますけれど,
その通りです。
>これらは各種メンバ関数の宣言その他もろもろからして違うので
>汎用に扱おうとするのはかなり無理がないですか?
無理がありました(汗 いろんなことが出来ませんでした。
とりあえず設計が悪かったということみたいです。

481:デフォルトの名無しさん
05/05/09 18:52:39
>480
それがやりたいならstd::vectorやstd::dequeをラップして
std::mapの要求に合うようにするアダプタ作るのが恐らく最良じゃないかと思います.
それを状況に応じてstd::mapととっかえひっかえする感じで.

482:デフォルトの名無しさん
05/05/10 00:38:29
boostにそんな感じのクラスなかったっけ?
似たようなニーズがあってboostを眺めたらあったので後で余裕があったら使おうと
思いつつ、遅いけどその場はstd::listで済ませたという覚えがある。
そういやその後試してなくてそのままになってるな。


483:デフォルトの名無しさん
05/05/10 00:43:11
multi_index_container

484:デフォルトの名無しさん
05/05/10 00:59:28
>>482
キーと値のアクセスの汎用化、ということなら property_map なんかもそうかな。
あとは boost-sandbox に associative_vector,vector_set なんてのもあるみたいだね。

485:デフォルトの名無しさん
05/05/10 01:05:27
>>480
まあ実用性のことは置いておいて、メタプログラミングのいい勉強になるかな、
と思ってちょっと書いてみた。
ここは BOOST スレじゃないので、敢えて boost::mpl とかは使わず。

template <class T0, class T1>
struct is_same_type {
 static const bool value = false;
};
template <class T>
struct is_same_type<T, T> {
 static const bool value = true;
};

struct sfinae_type {
 typedef char one;
 typedef struct { char arr[2]; } two;
};

template <class T>
struct has_key_type : sfinae_type {
 template <class U> static one test(typename U::key_type*);
 template <class U> static two test(...);
 static const bool value = (sizeof(test<T>(0)) == 1);
};
template <class T>
struct has_value_first_type : sfinae_type {
 template <class U> static one test(typename U::value_type::first_type*);
 template <class U> static two test(...);
 static const bool value = (sizeof(test<T>(0)) == 1);
};

486:デフォルトの名無しさん
05/05/10 01:06:01
template <class T, bool HasKeyType, bool HasValueFirstType>
struct A_specialized_impl {
 static const bool value = false;
};
template <class T, bool HasValueFirstType>
struct A_specialized_impl<T, true, HasValueFirstType> {
 static const bool value =
  is_same_type<int, typename T::key_type>::value;
};
template <class T>
struct A_specialized_impl<T, false, true> {
 static const bool value =
  is_same_type<int, typename T::value_type::first_type>::value;
};

template <class T>
struct A_specialized
 : A_specialized_impl<
   T,
   has_key_type<T>::value,
   has_value_first_type<T>::value
  > {};

template <class T, bool Specialized = A_specialized<T>::value>
struct A { ... }; // 通常版

template <class T>
struct A<T, true> { ... }; // 特殊化版

487:デフォルトの名無しさん
05/05/10 02:23:21
>485
細かいことですけどmapのkey_typeってconstですよ.

SFINAEのこういう使い方はあくまで
「必要条件を満たさないものを振り落とす」ってだけなんですよね.
それにできることが基本的な型特性と内部型の存在のテストくらいだし・・・.
せめてメンバ関数の存在をテストできればもう少し面白いと思うんですけれど.

488:デフォルトの名無しさん
05/05/10 03:24:21
>>487
いや、value_type が pair<const Key, T> なのであって、
key_type は Key のままだよ。
そうでないと一時変数作れないし。

489:デフォルトの名無しさん
05/05/10 09:27:04
>>487
> せめてメンバ関数の存在をテストできればもう少し面白いと思うんですけれど.

typeof(メンバ関数)で何とかなります。


490:デフォルトの名無しさん
05/05/10 10:28:50
>488
マジボケしてました・・・.

>489
何とかなります?typeofってそもそも非標準ですし.

491:ヽ(´ー`)ノ ◆.ogCuANUcE
05/05/10 10:36:09
>>490
まだ sandbox だけど boost::typeof とか。
boost スレかどっかで見たけど、どこだったか忘れた。

492:デフォルトの名無しさん
05/05/10 14:30:49
>>489
これとか見ると、メンバ関数のシグネチャが分かれば
なんとかできそうな気はする
URLリンク(lists.boost.org)

493:デフォルトの名無しさん
05/05/10 22:34:40
>>491
typeofがあってもメンバがなければ単にコンパイルが失敗するだけじゃないですか?

>>492
汎用プログラミングの文脈だと「~~というシグネチャを持ったメンバ関数があるかどうか」というテストより
「~~という構文でメンバ関数が呼び出せるかどうか」というテストの方が重要だと思うので,
そこで使われている技法は少なくとも汎用プログラミングでは非常に使いづらいような気がします.
それにその技法,言語規格的に結構スレスレなことやってるので,GCCではうまく通らなかったり
VC7.1でもうまく機能しないケースがあったり・・・.

494:デフォルトの名無しさん
05/05/11 00:30:14
>>493
> typeofがあってもメンバがなければ単にコンパイルが失敗するだけじゃないですか?

traitsみたいなんじゃ不十分で、条件分岐とかしたいという事?

495:ヽ(´ー`)ノ ◆.ogCuANUcE
05/05/11 10:34:33
>>493
失敗するだけだね。boost::mpl::has_xxx とかで何とかできないかとも思ったが、
寝不足なせいか、頭がこんがらがってきた。


496:デフォルトの名無しさん
05/05/11 19:59:54
>>494
そうです.traitsというよりはintrospectionといったほうが適切ですかね.
traitsはユーザが明示的に特殊化する分,確実ですけれど一方で面倒な側面もあると思うので,
ある程度は要件を自動的にテストしてくれたほうが楽かなという発想です.

>>495
boost::mpl::has_xxxは内部型の存在テストにしか使えないです.

497:デフォルトの名無しさん
05/05/12 00:23:09
>>496
> そうです.traitsというよりはintrospectionといったほうが適切ですかね.

traitsとも違い、
virtual classをinheritしたり、
interfaceをimplementsするのとは違う用途は、
具体的にどういうものを想定しているんですか?

498:デフォルトの名無しさん
05/05/12 03:28:39
>>497
>具体的にどういうものを想定しているんですか?
いや,あまりろくなことを考えていないんですが,一応,型がどのコンセプトの
モデルなのかを識別するための手段として使えないか,と想定していました.
型がどのコンセプトのモデルであるかを識別できれば,クラステンプレートの特殊化や
汎用関数のオーバーロード選択をより柔軟にできるんじゃないかという考えです.例えば

template<class Iterator, class T>
void replace(Iterator first, Iterator last, T const &x);

という汎用関数があって,TがIteratorの値型に変換可能な型ならstd::replaceの機能で,
TがIteratorの値型を受ける単項述語ならstd::replace_ifの機能といった具合です.
逆に言うと,STLはこのようなコンセプトに基づいたオーバーロード選択の技術がないので
replaceとreplace_ifとに名前を分けざるを得なかった,とも言えると思います.
で,仮に例えばTのoperator()がIteratorの値型で呼び出せるかどうかを
テストできるような実装技術があれば,traitsの明示的な特殊化に頼ることなく
上記のような高度な振り分けができるんじゃないか,という考えです.
ただ,もちろんメンバ関数の存在テストはコンセプトの必要条件を調べられるだけで,
決してコンセプトのモデルであるための十分条件を調べることにはならないのですが・・・.

499:デフォルトの名無しさん
05/05/12 03:29:37
・・・ということを想定していたんですが,

URLリンク(tinyurl.com)

上のような議論を見つけたので読んでみた結果,やはりtraitsの特殊化などで
明示的に表明する方が良いような気がしてきました.より根本的には
言語としてこういうことを直接サポートしてくれればもっとうれしいのですけれど.

URLリンク(www.open-std.org)

500:デフォルトの名無しさん
05/05/12 12:05:02
上記PDFもそうだけど、D&Eの書き下ろし前文(-1章)を見ても、
コンセプト回りの拡張が c++0x でなされる可能性は高いんじゃないかな。

ただ、Stroustrup としても
テンプレート回りのエラーメッセージの酷さを何とかすることや、
テンプレート宣言と定義の分離問題を何とかするために導入したいような
感じだし、基本的にはコンパイル時検査の強化を目的としたものであって、
オーバーロード選択などに使われるようなものではないと思う。

例えば、関数ポインタのシーケンスがあったとして、
operator== による find なのか、operator() による find_if なのか、
コンセプトだけでは判断できないケースもあるわけで。

501:デフォルトの名無しさん
05/05/12 19:39:36
>>500
> 使われるようなものではないと思う。

けど,使われるようなものではないものに,使われて驚くのがtemplateだしなあ…

502:デフォルトの名無しさん
05/05/13 01:07:52
>>500
>テンプレート回りのエラーメッセージの酷さを何とかすることや、
>テンプレート宣言と定義の分離問題を何とかするために導入したいような
これは前々からずっと言ってますからねぇ.近い将来標準に導入されると信じていますけれど.

>例えば、関数ポインタのシーケンスがあったとして、
>operator== による find なのか、operator() による find_if なのか、
>コンセプトだけでは判断できないケースもあるわけで。
う,やはりここ突っ込まれますよね・・・.こういう曖昧なケースではユーザが
明示的に曖昧性を解消するような方向を想定してました.微妙ですけれど.

やはり現在の段階では,コンセプトに基づくオーバーロード選択や
テンプレートの特殊化といった発想は飛躍しすぎている感がありますね.

503:デフォルトの名無しさん
05/05/14 03:29:59
参照templateのパラメータに制限あるのかな?
グローバル変数しか使えないみたいなんだが...

struct A{};
template <A& a>struct C{};

A a;//OK

int main()
{
A a;//NG
C<a> c;
}


504:デフォルトの名無しさん
05/05/14 05:10:48
>503
14.3.2 Template non-type arguments
4 [Note: Temporaries, unnamed lvalues, and named lvalues that do not have external linkage
are not acceptable template-arguments when the corresponding template-parameter has reference type.
14.3.2-1 の補足。

505:デフォルトの名無しさん
05/05/14 09:10:05
テンプレートはコンパイル時に生成されるわけで
mainの方のaは実行してみないとどこに作られるかわからないわけで
そのaをテンプレート引数にstruct Cは生成できないわな。

506:デフォルトの名無しさん
05/05/15 21:00:03
VisualC++7.1なんですが、テンプレートコンストラクタの明示的なインスタンス化をしたいんですが
コンパイルが通りません。なぜでしょうか?

class A
{
public:
template< typename B > A( B b){;}
};

template< > A::A< int >( int b); // error C2143: 構文エラー : ';' が '<' の前にありません。 他
template A::A< int >( int b); // error C2143: 構文エラー : ';' が '<' の前にありません。


507:デフォルトの名無しさん
05/05/15 21:28:04
>>506
URLリンク(www.kuzbass.ru)
ここに明示的な特殊化の対象となるものがリストされているんだが、
"member function template of a class template" はあるけど、
"member function template of a class" は無いな。

できないのかもしれない。

508:デフォルトの名無しさん
05/05/15 21:51:51
>>506>>507
多分これ。
14.5.2.5
[Note: because the explicit template argument list follows the function template name,
and because conversion member function templates and constructor member function templates
are called without using a function name, there is no way to provide an explicit template argument list
for these function templates. ]
コンストラクタは関数名を持たないので、メンバテンプレートにされたコンストラクタおよび
変換メンバ関数テンプレートは明示的に実引数を与えられないって事っすね。
C++の不具合とも言えるので、次期C++規格ではfixして欲しいですな。

509:デフォルトの名無しさん
05/05/15 21:56:00
>>506
理解しました。ありがとうございました。
しかし皆さん凄いですね。

510:デフォルトの名無しさん
05/05/15 21:56:33
>>506
というわけで
「コンストラクタテンプレートぐらいhppに全部書いちゃえば良いじゃない」
もしくは
「コンストラクタテンプレート内の処理を静的メンバ関数に委譲して
(この部分だけはhppに書く必要アリ)
委譲先の静的メンバ関数を明示的にインスタンス化すれば良いじゃない」

511:デフォルトの名無しさん
05/05/15 22:32:53
ん?これでできてるっぽいぞ。
template<> A::A( int b);

512:デフォルトの名無しさん
05/05/15 23:29:21
>>511
あれ?本当だね。という事は、template <>の構文がちゃんとメンバテンプレート
に適用されているみたいだね。俺の勘では、明示的特殊化になってなくて、単なる
オーバーロードのような気もするが・・・・

513:デフォルトの名無しさん
05/05/15 23:36:57
もう少し規格票をよく読んでみる・・・・・
>>508はそしたら違う事に関してなのかな。

514:デフォルトの名無しさん
05/05/15 23:41:09
>>511
しかし、そのコードは構文的に正しいとは言えないですよね。
謎だ。


次ページ
最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch