【C++】template 統合スレ -- STL/Boost/Loki, etc.

このエントリーをはてなブックマークに追加
1デフォルトの名無しさん
C++ のジェネリックプログラミングの話をしましょう。
以下のスレッドを統合するスレです。

STLスレッド
Part1 http://pc.2ch.net/tech/kako/1004/10042/1004287394.html
Part2 http://pc3.2ch.net/test/read.cgi/tech/1026793823/

【C++】Boost使い集まれ!
http://pc3.2ch.net/test/read.cgi/tech/1033830935/

Generic Programming with C++ Template
http://pc.2ch.net/tech/kako/1008/10085/1008593126.html

関連スレ、その他リンクは >>2-5 あたりに。
重複スレで良いな?
boost固有の話は boostスレでやってくれていいけど、いずれは
このスレに統合するってことで。
>>1
乙カレー
C++標準以外のものは使うな。よってSTLのみとする。
スレ立ったの見て一瞬 (゚Д゚)ハァ? と思ったが、後で合流するならいいか。
>>1-2
乙ー
カレー

マターリ逝きましょう
12デフォルトの名無しさん:02/11/21 01:04
#include <memory>

class B {};
class D : public B {};

std::auto_ptr<B> f()
{
  std::auto_ptr<D> p;
  return p;
}

↑の一見通りそうだけど、エラーになります。
test.cpp:9: no matching function for call to `std::auto_ptr<B>::auto_ptr(
std::auto_ptr<B>)'
/usr/include/c++/3.1.1/memory:346: candidates are:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr_ref<_Tp>) [with _Tp = B]
/usr/include/c++/3.1.1/memory:216:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp1>&) [with _Tp1 = B, _Tp = B]
/usr/include/c++/3.1.1/memory:203:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp>&) [with _Tp = B]
test.cpp:9: initializing temporary from result of `
std::auto_ptr<_Tp>::operator std::auto_ptr<_Tp1>() [with _Tp1 = B, _Tp = D]'

とりあえず、
  return std::auto_ptr<B>( p );
で、エラーにならなくなるようです。
この修正が妥当なんでしょうか?
>>12
std::auto_ptrが継承に対応してないからかと思ったけど、どうも区別が
曖昧だというエラーが出るね。
14:02/11/21 02:13
なかなか難しいよね。templateベースのものは。
まあ仕事にも使った事はあったけど。便利なんだけど。
継承は対応してないのか。確かに通らんね。

#include <memory>

class B {};
class D : public B {};

std::auto_ptr<B> f()
{
std::auto_ptr<D> p;
return dynamic_cast<std::auto_ptr<B> >(p);
}
auto_ptr<B>とauto_ptr<D>は単に別の型であって、
暗黙の型変換ができなかった、ということでは?

>>15
そこでdynamic_castを思い浮かべてしまうというのは
ちと知識不足すぎやしませんか。ネタ?
>>16
いや(汗、本当に継承に対応してないのかと思って。
でもパラメタの型が違うから当たり前か・・・・
1812:02/11/21 10:55
>>16
ttp://www.kuzbass.ru/docs/isocpp/lib-utilities.html#lib.auto.ptr
↑には、
>template<class Y> auto_ptr(auto_ptr<Y>&) throw();
>Requires: Y* can be implicitly converted to X*.

>template<class Y> auto_ptr& operator=(auto_ptr<Y>& a) throw();
>Requires: Y* can be implicitly converted to X*. The expression delete get() is well formed.

っていうインターフェースがあるようで、
auto_ptrの規格は、>>12の最初のコードが
コンパイルできるように配慮されているように見えます。

同時に、余計な変換手段に見えるインターフェースもありますが・・・。
よく読み直してみろ
20デフォルトの名無しさん:02/11/21 22:19
統合スレになったとたんレベルが...
C言語スレみたいにバカをネタにしてつきあうぐらいの寛大さが必要です
22デフォルトの名無しさん:02/11/21 22:33
でも確かに、何でstd::auto_ptrにキャストオペレータ入れなかったんだろうとは思うね。
std::auto_ptrってどんなメンバ関数があるのだろう?
> std::auto_ptrにキャストオペレータ

作るとしたらどんなコーディングになる?
template<class T, class U>
std::auto_ptr<T> cast(std::auto_ptr<U>& ref)
{ return std::auto_ptr<T>( ref.release() ); }
と、やりたいけど出来ないんだよな
そうじゃなくて、自分がauto_ptrの設計者だとしたら。
2712:02/11/22 00:43
>>19
読み直してみたけど、新しく気づいたことはなかったです。

・・・やっぱりわからん。
<memory>を読んでみたけど、変換インターフェースの実装のところに、
「派生関係の変換が可能になるように、これらのモノが必要」みたいなコメントまで書いてある。
コメント中にあるサンプルと同様のコードをコンパイルしようとしたけど、
やっぱり>>12と同じエラーになる。

モッカイageテミル
>>25
release()必要ないのでは?std::auto_ptrのコンストラクタは所有権を
移動させるから。
auto_ptr<T>とauto_ptr<U>の互換性があるかどうか分からないのに、
どうやって所有権を移動させるんだ?
継承と同じように考えて、親クラスのポインタ変数に子のオブジェクトのアドレス
を代入できるかと自然と考えてしまいました。でもstd::auto_ptrは継承とか考慮
してないので、エラーになるのですね。
>>12
むしろ継承関係にあるからこそのエラーと思われ。
継承関係になかったら別のエラーになるけどさ。

gcc-2.95.3 でcompileしてみた。
conversion from `auto_ptr<D>' to `auto_ptr<B>' is ambiguous
: candidates are: auto_ptr<D>::operator auto_ptr<B><B>()
: auto_ptr<B>::auto_ptr<D>(auto_ptr<D> &)

>>29
互換性があればcompileできるだろ?
3231:02/11/22 02:23
あぁ >>25 のままじゃcompileできんな
template<class T, class U>
std::auto_ptr<T> cast(std::auto_ptr<U>& ref, std::auto_ptr<T>&)
{ return std::auto_ptr<T>( ref.release() ); }
だね。

つーか、むしろ
template<typename T, typename U>
T cast(U &ref, T &) {return T(ref.release());}
33デフォルトの名無しさん:02/11/22 03:52
3412:02/11/22 07:33
>>32
そのテンプレート関数はどうやって呼び出すんだ?

template<typename Y> std::auto_ptr<X>::auto_ptr( std::auto_ptr<Y>& r );
template<typename Y> std::auto_ptr<X>& std::auto_ptr<X>::operator = ( std::auto_ptr<Y>& r );
template<typename Y> std::auto_ptr<X>::operator auto_ptr<Y>();
↑キャストなんて標準で装備されてるこれらで十分のはずだ。
3531:02/11/22 11:01
>>34
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
2!
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
 え
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
  
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
       
>>31
通常時、TとUには互換性があるかも知れないが、
auto_ptr<T>とauto_ptr<U>に互換性があるときはT==Uの時だけだろ。
一体このスレは何が起きているんだ?
>>42
もう後には引き下がれない意地と意地のぶつかり合いが
繰り広げられています。
異常なほど向きになっておりますな。
しかも会話がかみ合っていないときている。
意見が噛み合ってないのは議論じゃなくて論破しようとしてるせい。
ん?
とりあえず、前の発言者のレスを引用して、(゚Д゚)ハァ? とか書けばいいわけか?
4712:02/11/22 20:16
>>31
器用な人ですな。

> で、>>31 の内容は理解できましたか?
え・・・?理解できません、たぶん。
あと、キャストする関数の引数が二つなのが理解できませんねぃ。
> ん?
> とりあえず、前の発言者のレスを引用して、(゚Д゚)ハァ? とか書けばいいわけか?

(゚Д゚)ハァ?
> > ん?
> > とりあえず、前の発言者のレスを引用して、(゚Д゚)ハァ? とか書けばいいわけか?
>
> (゚Д゚)ハァ?

(゚Д゚)ハァ?
50デフォルトの名無しさん:02/11/22 20:59
時期ヴァージョンのJava(J2SE1.5)でJavaGenerics(?)がコアAPIに統合されテンプレートが使えるようになり、コレクション系インターフェースの問題が
解消されるというのでちょっと期待しているのですが
C++でテンプレートを使うメリット、デメリットとはどんなものでしょうか?

投稿記事のC++ソースを見た感じ、複雑そうに見えます。
テンプレートを使いこなすには修行が必要そうですね。
STL ライクなコードが Java で書けるというだけで、template が使える
というのとは違うと思っていたが気のせいか?
5231:02/11/23 02:19
>>37-40
すげぇ、これこそまさにテンプレートなんだね。感心。

>>41
> auto_ptr<T>とauto_ptr<U>に互換性があるときはT==Uの時だけだろ。
いや。 >>18 とか >>34 にも書いてある。
それを、互換性がある、と言わないとか、
class B {}; class D : public B {}; のときは B == D というなら
そういうもんなのねとあきらめる。
5331:02/11/23 02:20
>>47
> あと、キャストする関数の引数が二つなのが理解できませんねぃ。

#include <memory>
template<class T, class U> std::auto_ptr<T> cast(std::auto_ptr<U>& ref)
{ return std::auto_ptr<T>( ref.release() ); }

template<class T, class U> std::auto_ptr<T> cast(std::auto_ptr<U>& ref, std::auto_ptr<T>&)
{ return std::auto_ptr<T>( ref.release() ); }

class B {};
class D : public B {};
main() {
std::auto_ptr<B> b;
std::auto_ptr<D> d;
b = cast(d, b);
b = cast<B>(d);
}

でどうよ。
これは通るけどこれでもいいの?

template<class T, class U> std::auto_ptr<T>
cast(std::auto_ptr<U>& ref)
{
return std::auto_ptr<T>(std::auto_ptr<U>(ref));
}
>>54
その関数実際に呼んでみた?
>>55 読んでみました。この通りです。

class A {
public:
int i;
};

class B : public A {
public:
int j;
B(int x, int y) { i = x; j = y; }
};

template<class T, class U> std::auto_ptr<T>
inline cast(std::auto_ptr<U>& ref)
{
return std::auto_ptr<T>(std::auto_ptr<U>(ref));
}

int main()
{
std::auto_ptr<B> ptr(new B(123, 456));
std::auto_ptr<A> pa;

pa = cast<A>(ptr);

std::cout << pa->i << std::endl;

ptr = cast<B>(pa); // ダウンキャストはだめ?

std::cout << ptr->j << std::endl;
}
で、

pa = cast<A>(ptr);

は通るんですが、

ptr = cast<B>(pa); // ダウンキャストはだめ?

はだめなんです。もっとも、この行はrelease()を使った版でも
通りませんでした。
>>56-57
何、通るの!?

げ、STLportだと通るよ。

> ダウンキャストはだめ?
reinterpret_castしてるわけじゃなくて
pointerのoperator=だからねぇ。
>>58
gcc3.2でも通るよ。

>reinterpret_castしてるわけじゃなくて
>pointerのoperator=だからねぇ。

あっそうですね。考えてみればそうだ。
>>12 の話に戻るけどさ、

auto_ptr<B> p = auto_ptr<D>(); // (1)
p = auto_ptr<D>(); // (2)

g++ 3.1 で (1) が通らないんだけど、
誰か解説してくれ
>>60
auto_ptr<型>()はコピーコンストラクタだからじゃない?
>>60
スマソ。std::auto_ptr(T* p = 0) はコンストラクタだね。

ところで
std::auto_ptr<B> p = std::auto_ptr<B>(std::auto_ptr<D>());
は通るよ。
んー、ということは、std::auto_ptrの代入演算子とコピーコンストラクタの
書き方に対称性がないということになるね。
6460:02/11/23 04:39
あとね
auto_ptr<D> d;
auto_ptr<B> b0(d); // OK
auto_ptr<B> b1 = d; // NG
なのよ。

auto_ptr<B> b2(auto_ptr<D>());
はfunction declarationになっちゃうからいいんだけど。
>>64
それは、std::auto_ptrのコンストラクタがexplicit宣言されている事と
関係があると思う。
つまり、

auto_ptr<B> b0(d); // OK

の時はコンストラクタを呼び出してくれるけど、

auto_ptr<B> b1 = d; // NG

の時はコピーコンストラクタが呼び出されてしまい、それが
buggyなのでエラーになるかと。違うかもしれんけど。
いろいろ調べてみたら、std::auto_ptrには

template class<T>
operator std::auto_ptr<T>()

という変換演算子があるらしい。この格好がコピーコンストラクタと
酷似しているため、コンパイラが混乱してしまうようだ。

だから明示的にコピーコンストラクタを呼び出してやればいいと思う。
最初の

#include <memory>

class B {};
class D : public B {};

std::auto_ptr<B> f()
{
std::auto_ptr<D> p;
return p;
}

に戻ってみると、return p; の時点で、
std::auto_ptr<D>をstd::auto_ptr<B>にコピーするコピーコンストラクタを
呼び出すか、std::auto_ptr<D>をstd::auto_ptr<B>に変換する変換演算子
を呼び出すか曖昧だからエラーが出たようだ。
そうすると、
return std::auto_ptr<B>(p);は、コピーコンストラクタなのか、それとも
変換演算子なのか?誰か教えてください。
さらに深く調べると、
return std::auto_ptr<B>(p); もエラーになるのは、これもコピーコンストラクタか
変換演算子なのか曖昧だという事がわかった。

エラーを回避するには、
std::auto_ptr<B> f()
{
std::auto_ptr<D> p;
return std::auto_ptr<B>(std::auto_ptr<D>(p));
}

のように書かなければいけないようだ。この場合コンパイル出力をアセンブリ出力
で見てみると、コピーコンストラクタを呼び出した後変換演算子が呼び出されていた。
7160:02/11/23 13:29
>>65-70
えらい!

しかし、もーtemplateの話じゃないねぇ。

http://gcc.gnu.org/ml/gcc-help/2001-07/msg00137.html
同じ話ハケーン

http://www.kuzbass.ru/docs/isocpp/decl.html
8.5.14の最後の方の段落で説明されているようだ。
>>71
ちょっと違うかもしれないが、だいたいこれと同じような現象が起こって
いるようです。

class B;

class A {
public:
A() {}
A(B*) {}
A(B&) {}
};
class B {
public:
operator A() { return A(this); }
};

int main()
{
A a;
B b;
a = b;
}
関数も付け加えてみました。スレ違いにてここまで。

class B;

class A {
public:
A() {}
A(B*) {}
A(B&) {}
};
class B {
public:
operator A() { return A(this); }
};

A f(B& b)
{
return b;
}

int main()
{
A a;
B b;
a = b;
f();
}
あっ、f()でなくてf(b)です。
7512:02/11/23 18:33
>>70
return std::auto_ptr<B>(p);
これはエラーにならずに通るぞ。
>>69
こういうのは、「変換コンストラクタ」とか言うんじゃないの?
ちなみに、 std::auto_ptr に「コピーコンストラクタ」は無いと言える、よね?
std::vector<std::string> str;
と宣言して
str.push_back(buf); (bufはchar型の文字列)
という感じで値をつめていくと「識別子が '255' 文字に切り捨てられました」
とコンパイラの警告が出ます。char型の文字列をどんどん追加していきたいのですが、
正しい値の代入の仕方があれば教えてください。
>>76
それは文字列が切りつめられたんじゃなくて、
templateを展開した型の実名が長すぎるから切りつめられただけ
>>76
VC++6.0の仕様
あきらめれ
#pragma warning(disable:4503)
#pragma warning(disable:4786)
で黙らせる。
俺ら最強!YO!
>>65-74
おつかれさま。
チョピーリチミを好きになりますた。
82デフォルトの名無しさん:02/11/24 11:40
auto_ptrは解決したようなので...

何度も出てる質問だと思うけど、boost仕事で使ってる?
オレんところは小さい会社だし、仕事がR&D的だし、
わがままは通るから勝手に使っちゃってるけど。
templateやSTLでさえも使えない会社って多いんでしょ?
(ならC++なんか使うなって感じだけどな。)
ここのスレの人はgcc使ってるの?
環境がwindowsだとmingw?
>>83
ワシはBCB6れす。boost::lambda使いたいよ〜。
cygwin-bccはまだ2.95だよね?
オレは g++ 3.2 を使って開発してから vc++ に移植、ってパターンが
多いかな。もちろん boost のスマートポインタが無いと仕事になりません。
次期vc++は、boost も loki もちゃんと通るらしい(というか、コンパイル済み
オブジェクトが添付されるらしい)ので楽しみ。↓参照。
http://www.zdnet.co.jp/enterprise/0211/11/n20.html
SDKのコンパイラも新しくなるのかな?
87デフォルトの名無しさん:02/11/24 12:27
51>>
C++のテンプレートそっくりなものをそのまま使えるわけでは無いようですが、これによりJavaの型キャストの問題に悩まされなくなり、instanceof修飾子を使わずに済むようになり、よりオブジェクト指向的なコードがかけるようです。
>>85
g++使って書いたコードって、VCでコンパイル通る?
俺はだめだ。template周りが弱すぎるよ、VCって。
そんなわけでVCはほとんど使えない。辛うじてBCBかな。
>>85
コンパイル済みオブジェクトが添付されるって、
exportがサポートされるってこと?それはすごい!!!
90デフォルトの名無しさん:02/11/24 13:31
template <int M, int N=1>
class StaticArray{
public:
inline static const double* init(){
(N-1<M)?(StaticArray<M,1>::data[N-1]=double(N-1)):0;
StaticArray<M,N-1>::init();
return StaticArray<M,1>::data;
}
};
template <int M>
class StaticArray<M,1>{
static double data[];
public:
inline static void init(){ StaticArray<M,1>::data[0]=0;}
template <int,int>
friend class StaticArray;
};
template <int M>
double StaticArray<M,1>::data[M];
int main(){
const double* array=StaticArray<20,10>::init();
for(int i=0;i<20;i++) std::cout << " " << array[i];
std::cout << std::endl;
}
http://pc.2ch.net/tech/kako/1008/10085/1008593126.html
でいってたすたちっくに配列の初期化するのってこんなんだろか
>>88
さすがに export は無理じゃろ。
たんにregexとかのライブラリがコンパイル済みで提供される、
ってことだと思う。
>>91
Lambdaが使えるなら、それでもいいかも。
>>91
いや、そうでもないんじゃない?
C# にジェネリクス実装するのなら、結局 C++ の export 相当の機構が必要になる。
MS 内部でどういう開発グループ分けになってるかは知らないけど、
彼らが知識共有していくとしたら…。
>>93
C#じゃなくてVC++でしょ(8.0だっけ?)
標準に98%準拠っていうあれでしょ。

でも今ので90%だって自称してるんだから期待できないけど。
9593:02/11/24 14:32
>>94
おわかりですか?
export が VC++ に実装されるって話題です。
C# で同等の技術が必要になるから C++ でもやるんではないか?
という事です。

というか 98% の残りの 2% はいったい何なんだ。
98っていう数字がなんだか微妙だよね(藁
>>93
C#とJavaのGenericsは基底クラスがあるからなぁ。
C++でうまくいくのかなあ。
残り2%がtemplate周りだったらいやだなぁ。
うまくいくならVC8買っちゃうんだけど。
ttp://pc3.2ch.net/test/read.cgi/tech/1033830935/ の322が
何か言ってるんだが、誰か心当たりは?
2ちゃん内に対するリンクを切るのは止めてくれ。
export とベースクラス Object/object がある事って関係ないんじゃ?
>>98
http://www.codeproject.com/interview/stanlippman14nov2001.asp
> Microsoft’s goal is to have a ‘competitively compliant’ compiler -
> meaning it won’t be 100% compliant. There are a couple of features
> of the ANSI/ISO standard (for instance the ‘export’ keyword as
> applied to template classes) that won’t be implemented because
> they are considered by Microsoft to be obscure and, at this stage,
> theoretical.
とか。ただ、exportなんでEDGのですらサポートされてない
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpdndeepc/htm/deep04202000.asp
とか言えた時代と違って、すでにexportが使えるコンパイラが
登場してきてるからには、認識も変化しているかもしれないけど。

>>100
C#のGenericsはどうなるのか知らんけどJavaのGenericsは例えば、
「内部では全てObjectへの参照を保持するようなコンテナをオブジェクトコードとして
生成しておいて、それを利用するソース側のコンパイル時に型チェック/自動型変換を
かける」 みたいな方法で実装してるだけだから参考にならん、という面はあると思うが。

C++にも「Object型があって、変数は全てポインタ」みたいな
制限があればtemplateのexportは相当楽になるわけで。
102デフォルトの名無しさん:02/11/24 20:02
STLのmapについての質問なのですが、
「mapの要素の挿入と削除には対数時間(logN)が必要ですが、
位置を指定して要素を挿入する場合は償却定数時間(ε)しかかりません。」
と本にあったのですが、いまいちよく分かりません。
(1)削除
void erase(iterator i); -> logN ?
void erase(iterator start,iterator end); -> length*logN ?
size_type erase(const key_type &k); -> logN ?
(2)挿入
iterator insert(iterator i,const value_type &val);-> ε ?
template<class InIter>
void insert(InIter start,InIter end ); -> length*logN ?
pair<iterator,bool> insert(const value_type &val);-> logN ?
であってますでしょうか?
>>102
位置指定が正しい場合にのみ、定数時間で挿入ができるらしい。
ttp://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html

で、「正しい位置」は lower_bound で取れる。
104102:02/11/25 15:09
「反復子で指定した要素の削除は定数時間です。」を忘れてました。
void erase(iterator i); -> ε に修正します。

>>103
[挿入|削除]する[位置|反復子]が分かっているときは定数時間だが、
その位置を探すのにlower_bound ->logN 時間かかるということですかね。
ありがとうございました。


105デフォルトの名無しさん:02/11/26 19:20
type_of演算子作りたいんだけど。

コンパイラがどの型にも固有の値を割り振っていて、
それをコンパイル時に参照できたら
式templateとマクロでtype_of作れるんだけど、
静的使えるのがsizeofしかないぽいから無理くさいのかな。

//ないんでとりあえず実験
#define class_id(x) sizeof(x)

template <int> struct Type_of;
struct Type_of<class_id(int)>{typedef int type;};
struct Type_of<class_id(char)>{typedef int type;};

#define type_of(x) Type_of<class_id(a)>::type

#include<iostream>
int main()
{
int a;
char c;
type_of(a) a2=200;
type_of(c) c2=100;
std::cout << a2 << c2;
}
106105:02/11/26 19:31
修正:
× struct Type_of<class_id(char)>{typedef int type;};
○ struct Type_of<class_id(char)>{typedef char type;};
107>>105:02/11/26 21:34
VC++7.0 限定でよければ…(C++の規格的には間違っているらしい)
-----------------------------------------------

typedef char (&no_tag)[1], (&yes_tag)[2];
template<int> struct id_counter;
template<typename> struct t2t;
template<typename T> no_tag test(T*, ...);
#define EMPTY(n) sizeof(test((t2t< id_counter<n> >*)0))==sizeof(no_tag)

template<int val_ =
(EMPTY(1) ? 1 :
(EMPTY(2) ? 2 :
(EMPTY(3) ? 3 :
(EMPTY(4) ? 4 :
(EMPTY(5) ? 5 :
(EMPTY(6) ? 6 :
(EMPTY(7) ? 7 :
(EMPTY(8) ? 8 :
(EMPTY(9) ? 9 :
-1)))))))))> struct id_counter {
enum { val = val_ };
friend yes_tag test( t2t< id_counter<val> >* );
};

template<typename T> struct id_of { enum { val = id_counter<>::val }; };
#define class_id(T) id_of< T >::val
108107:02/11/26 21:37
#include <iostream>
int main()
{
std::cout << class_id(int) << ' '
 << class_id(int) << ' '
 << class_id(char) << ' '
 << class_id(int) << ' '
 << class_id(long) << ' '
 << class_id(std::istream) << std::endl;
}



1 1 2 1 3 4

になる。とゆーか、分割コンパイルまで考えると、コンパイラ的にはtypeofよりも
staticなTypeIdの方がよっぽど面倒な気がするので、素直にc++0xを待つべきかと。
109107:02/11/26 23:02
今思いついた。sizeofと同じく式に対しても使えるようにするには、こんな感じ。

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)

//int a; float b;
//assert( obj_class_id(a+b) == class_id(float) );
110105:02/11/27 11:30
>>107
すごすぎる!!!
id_counterってほんとにその名の通りですね。
少し手を加えて
type_ofとtestプログラム作ってみたけど、
こういうものはウプしてもいいのかな?(どういう場所がいいのか)
どうにか手を入れれば、GCCでも動かせそうな気がするんだけど、
自分では無理そうでした。
111デフォルトの名無しさん:02/11/27 14:20
>>107
逆に、IDから元の型を取得することはできないの?

float f = 1f;
int i = (class_id(int))f;

キャストに使えたりするとうれしい。
よく使う foo とか bar とかって、RFC で定義されてたんだな。
知らなかった。
http://www.puni.net/~mimori/rfc/rfc3092.txt
jokeだろ
>113
しっ!!
うお!IPってデータリンク層に鳩使っても使用可能なんだってさ!
RFC勉強になりすぎ。
116107:02/11/27 19:27
ネタ元は
http://lists.boost.org/MailArchives/boost/msg37791.php
ね。

>>111
それが出来ると typeof の完成なんだけど、思いつかないっす。
105氏のType_ofみたいに、必要なクラスのid - typeのマッピングを
全部手で書いていくくらいしか。何か上手い手はないかな。
117105:02/11/28 08:48
ttp://www3.to/typeof
にとりあえず上げてみました。
中を見ると分かるけど

>>111
int i = (type_of_id( class_id(int) ))f;
でできます。でもType_ofで登録した物にしか使えません。

>>107
ちょこっと追加として
int addfunc(int,int);
type_of_declare(addfunc(int,int),aa);
std::cout << aa;
とかできるようにした。(定義場所わかりにく...

>>107(116)
入れ子の式テンプレートでできないかと思ったけど撃沈...。(以下、略
template <typename T> struct Type_of_collection
{
template <int N> struct Type_of_Num;
struct Type_of_Num<class_id(T)> { typedef T type;};
};
118デフォルトの名無しさん:02/11/28 12:01
119デフォルトの名無しさん:02/11/28 15:05
質問です。VC++6.0で

#include <list>
using namespace std;
void main(){
list<list<int>> a:
}
というのでエラーがでます。
listのlistを作るにはどのようにしたらいいのでしょうか?
>>が引き篭もりなのです

>list<list<int>> a:
色々違ってるな。

122デフォルトの名無しさん:02/11/28 15:11
>120

ありがとうございました。
直りました。
123デフォルトの名無しさん:02/11/28 15:37
>>118
ただなの?
>C++ Compiler 7.0 for Windows \55,000
std::vectorのstd::sortが予想外に速い。インライン展開の賜物か。

const int N = 2000000;
int cmp(const void *, const void *);

int main()
{
static double d[N];
std::vector<double> vd;
std::clock_t ti;

std::srand(0);
for (int i = 0; i < N; i++) d[i] = std::rand();
std::srand(0);
for (int i = 0; i < N; i++) vd.push_back(std::rand());

ti = std::clock();
std::qsort(d, N, sizeof(double), cmp);
std::cout << "qsort = " << std::clock() - ti << std::endl;

ti = std::clock();
std::sort(vd.begin(), vd.end());
std::cout << "sort = " << std::clock() - ti << std::endl;
}
int cmp(const void* a, const void* b)
{
if (*static_cast<const double*>(a) < *static_cast<const double*>(b)) return -1;
else if (*static_cast<const double*>(a) > *static_cast<const double*>(b)) return 1;
return 0;
}

qsort = 906
sort = 734
intだと

qsort = 702
sort = 328

差が開く。
intでcmp()を

int cmp(const void* a, const void* b)
{
return *static_cast<const TYPE*>(a) - *static_cast<const TYPE*>(b);
}

に換えたらちょっと速くできるけどまだsort()の方が速い。よくできてるなあ。

qsort = 562
sort = 344
あっごめん、環境はBorland-C++5.6.2(STLport装備)ね。
130デフォルトの名無しさん:02/11/29 10:08
Win98SE、VC6SP5、PentiumIII-800。
STL は VC6 付属のもの。
コンパイラ付属のソースをインライン展開しまくった my_qsort でもやってみたよ。

double:
my_qsort = 4340
qsort = 4720
sort = 1760

int:
my_qsort = 1540
qsort = 3240
sort = 830

int (quick cmp):
my_qsort = 1430
qsort = 2520
sort = 830

どうも、インライン展開うんぬんより、アルゴリズムが根本的に違ってるように見える。
STL のソートって何ソートなの?
131 :02/11/29 10:16
sort って比較と入れ替えが処理のメインだから、そこが関数呼び出しになって
しまって最適化されない qsort は正直かなりのオーバーヘッドがあると思う。
>>130
qsort の方はよく知らんが、STL の方は、

基本はクイックソート
pivot には先頭・ど真ん中・末尾の要素の中央値を使う
要素数が小さくなってきたら挿入ソートに切り替える
あと、最新版では再起が深くなってきたらマージソートに切り替えるって機能も付いてたと思われ。
標準のstd::logical_and、std::logical_orの使い方がよくわかりません。
参考書を読むと、標準にはないbinary_composeと組み合わせて使うと
書いてあるのですけど、どういう意味なのでしょうか?
>>131
130 の 3 行目は読んでくれたか?
> int (quick cmp):
> my_qsort = 1430
> sort = 830
その関数呼び出しのオーバーヘッドが無い状態で、これだけ差があるの。

>>132
VC6 付属の qsort.c については、
> pivot には先頭・ど真ん中・末尾の要素の中央値を使う
> 要素数が小さくなってきたら挿入ソートに切り替える
これと同じっぽい
要素数 8 以下で挿入ソートに入る。
ただし、マージソートはやってなくて、再帰は使わずに goto で戻してる。

ネックになりそうなのは、STL の場合のように代入演算子が使えないので、
char 単位にデータ転送しているところかな。
でも、それを無理矢理 int 決め打ちの swap にしても、まだ sort() のが
速い。
> my_qsort = 1100
後は何だ?
>>133
binary_composeにはSGIのSTLやSTLportで定義されている。std::compose2
というヘルパ関数を持つ。

例えば _1 < 1 || 3 <= _1 という関数オブジェクトを作るには

std::compose2(std::logical_or<bool>(), std::bind2nd(std::less<int>, 1), std::bind2nd(std::greater_equal<int>, 3))

とすればよい。

boostではネーミングが異なり、boost::compose_f_gx_hyとなっている。
> ネックになりそうなのは、STL の場合のように代入演算子が使えないので、
> char 単位にデータ転送しているところかな。

double が異様に遅いのはこのせいだな。
インライン展開しまくり、かつ代入演算子に変えたら、sort() に肉薄した。

my_qsort = 1965
qsort = 4715
sort = 1753

でもやっぱり sort() のが遅いけど。


あと、↓でより正確に測れる。

#pragma comment(lib , "winmm.lib")
#define clock_t DWORD
#define clock() timeGetTime()
> でもやっぱり sort() のが遅いけど。

sort() のが速いけど。ですた。
> boostではネーミングが異なり、boost::compose_f_gx_hyとなっている。

スマソ。boost::compose_f_gx_hxとなっている。に訂正します。
>>136
そうだったのか。あらゆる型に汎用にするために、charでアラインされた
転送単位を持つためにqsort()は遅いのか。

ということはcharでsortするとそんなに差は出ないはずだな。

・・・・やってみた。

qsort = 265
sort = 282

測定誤差により、逆転する事もあるが、大ざっぱに測定するとqsort()の
方が速くなった。納得。
STLとboostを一度同じ土俵に上げて、そのよさを比較し、
なし崩しにboostを認めようという作戦ですか?

私は認めませんよ!>boost
141boost:02/11/29 18:24
>>STL
ごめんなさい
標準 boost → SB
次期STLは間違いなくboostからいくつかの機能を取り入れるだろうに。
144小技:02/11/29 22:18
template< class T, class U >
U hoge( T foo, U* = NULL )
{
...
}

// 使い方
hoge<string, int>( "第二引数はダミー" );
>>144
これのどこが技なのか・・・・・
よけーなオーバーヘッド食いそうだ
147107:02/11/30 01:45
>>117
> ttp://www3.to/typeof
素晴すぃ。

結局friendで勝手に定義を挿入するしかなさそう、と思ってその方向で
弄ってたんだけど、id_counter と違ってsizeof以上の情報を
オーバーロードされた関数からとってこなきゃいけないのがうまく行かなくて撃沈続き…。
>>144
VC6対策か?
>>145-146
わからんのか?ヒントは返り血
template<class T, class U>
U hoge(T foo, U* up = 0)
{
return *up;
}

int main()
{
hoge<std::string, int>( "第二引数はダミー" );
}

としてみてもなあ。。。。intが無駄に使われているような気がして
ならない。
>150
じゃなくて、ふつーに書くと返り値の型が異なるだけの関数は多重定義できん
という話でしょ。

template じゃなくても良いんだが

int foo();
void foo();

これは NG だが、

int foo(int);
void foo();

これなら行ける。

> intが無駄に使われているような気がして
とりあえず最適化有効にしてアセンブラ出力させてみ。
inline化されたら無駄な引数はなかったことになるだろうねえ
つまり、第二引数の型を変えて多重定義するためというものなのか?
今いち存在意義がわからんが・・・・・・
俺も今一分かってないんだが,

int GetValue("キー")
string GetValue("キー")

みたいなことができるってことかい?
155154:02/11/30 12:19
ごめん。なんか違うみたい・・・
具体的な使用例をあげてみてくれないかい?
>>153
templateの特殊化したいときとか使えるけど?

>>155
>>151に書いてあんだろ?アホか?
>>156
155 はそんなことをする理由を訊きたがっているんだぞ。

無理やり使いどころを考えると、template クラスで Factory 関数を使うときか?
158154:02/11/30 13:04
>>157
そういうことです
(だから>>154でわざわざ”GetValue"という関数名を使ったのですが伝わらなかったようで・・・)

>無理やり使いどころを考えると、template クラスで Factory 関数を使うときか?
うーん。確かに無理やりですね。

Widget MakeWidget() ※Widgetは基底クラス

ってするもんじゃないでしょうか。

同じ関数名で返り値が違うってのがそもそも想像できないんですが・・・。
159154:02/11/30 13:07
連カキすまん。

利用法が無いなら無いでいいんです。
「こういうこともできるよ」って例なのだとしたら。

でも実際に使いどころがあるんでしたら聞いてみたいのです。
>>151
それなら

template<class U, class T>
U hoge( T foo )
{
...
}
// 使い方
hoge<int>( "第二引数なんざ要らん" );

で十分では?古いヘタレコンパイラでどうなるかは知らんが。
>158
> 同じ関数名で返り値が違うってのがそもそも想像できないんですが・・・。
template を使って Mixin (あるいは Strategy パターン) をを書くときに使える。
>160
それだと、明示的に型を指定する必要があるのが難だなぁ。

パラメタとして関数オブジェクト、関数ポインタ、ともかく () つければ処理して
くれるモノ何でも渡せるようにしておくと、コードの汎用性が上がる(場合がある)。
163160:02/11/30 16:27
>>162
引数をtemplateにして型指定を緩くしとくと嬉しい、というのはその通りだけど、
この場合関係ないでしょ。(>>144のも同じく明示的な型指定が必要)

違うのは返値の型のみ、という関数を作りたいとき (例えばModern C++ Design の
Factoryパターンの話とか) の話でないの?
>>160
が通るコンパイラが有るなら教えてくれ。
>164
ないだろう。class を typename にすれば通るけど。
166デフォルトの名無しさん:02/11/30 17:45
class_idだけど、テンプレートの特殊化のときにちょっとだけ違うためだけに
同じもの作らなくて済ませることができそうな気がする。
これって実行時に判定してるのかな?
Tって静的だけどデバッガで見るとswitch文の中は最適化されてないみたいなんです。

template <typename T> struct FFF
{
FFF(T a=0)
{
switch( class_id(T) )
{
case class_id(char):
std::cout << "char" << std::endl;break;
case class_id(short):
std::cout << "short" << std::endl;break;
default:
std::cout << "other" << std::endl;
}
}

};

template <> struct FFF<int>
{
FFF(int a=0)
{
std::cout << "int" << std::endl;
}
};
167続き:02/11/30 17:48
int main()
{
//出力結果
FFF<int> fff1; //int
FFF<char> fff2; //char
FFF<short> fff3; //short
}

>>164
VC++.NET と Bcc5.51 と DigitalMarsC++8.31 と
g++3.2 と g++2.95 と Comeau C++4.31 と Intel C++6.0 では通ったが?
通らないコンパイラを教えてくれ。
169デフォルトの名無しさん:02/11/30 20:21
うっひょっひょ( ゚∀゚ )
170続き:02/11/30 21:10
class_id(char) ->1 (enum定数)
class_id(short) ->3 (enum定数)
直接は飛んでないけど、結局同じなんで問題ないか。
(↓最適化なしのものVC)最適化すると変わるんだろうか...。
; 168 : FFF<char> fff2;
mov DWORD PTR -416+[ebp], 1
cmp DWORD PTR -416+[ebp], 1
je SHORT $L23144
cmp DWORD PTR -416+[ebp], 3
je SHORT $L23145
jmp SHORT $L23146
>>153
たとえば >>53
>>21
ひどいことを言うなよ。お前だってアホだったろうが
>>172
ひどいことを言うなよ。
>>168
確か>>164の脳内コンパイルだと通りません。
ネタがないとスレが荒むな。
それもあるけど、昔と比べると荒れすぎ。
177164:02/12/03 22:36
>>168,174
悪りィ、TとUが逆転してるのに気付かんかった。
っていうかテンプレ引数の交換は気付きにくいからやめい。
>>177
やめい、って交換しなきゃ第二引数が省略できんだろ。
>>178

template<class T, class U>
T hoge( U foo )
{
...
}

hoge<int>("できますが何か?");
180160:02/12/04 00:51
>>177
ああ、なるほど。混乱させてすまなんだ。

U を使うのって Undeducible か何かの略かと思ってたんで>>144
同じに返値U、引数T、になるようにtemplateの方を変えたんだけど、
Tの次はUってことか。自分では2引数以上のtemplateを書くときは
T1、T2、 T3 ... なのでなぁ。
>>179
コロンブス的な発想にチトワラタ(w
素朴な疑問なんだけど
template<class T, class U>

template<typename T, typename U>
とは書かないの?
183160:02/12/04 01:27
>>182
個人的には、
・タイプ数減らしたい時はclass。
・template template parameter は class と書くので、
 何となく全部 class で統一したい気分の日は class。
・マジメに書くときはtypename。
漏れは最初に覚えたときにclassのみだったから
テンプレート引数はclassのみ使用。
typenameは
typedef typename T::iterator iterator;
とがぐらいしか使わない。
>>184
漏れはtypenameに直した。
ってか,intとかにも対応するのにclassって気持ち悪いんだよな。C++のintはクラスじゃないし。
186184:02/12/04 04:07
>>185
気持ちは分かる。
昨夜、”C++ Templates" をゲット
まだChapter 3までしか読んでないけど、なかなか良さげ
>>187
どこの出版社?(・∀・)イイ?
>>189
Addison-Wesley だが……出たばっかの洋書でふ
190189:02/12/04 14:03
× >>189
○ >>188
>>189
ありがd。俺も本屋行って見てくるよ。
>Addison-Wesley だが…
Addison-Wesley キタ─wwヘ√レvv~(゚∀゚)─wwヘ√レvv~─ !!!!
Addison-Wesley、もう大好き♪
分かりやすいし、詳しいし…。
>>183
俺は int などのプリミティブ型も引数に取る場合には typename, クラスしか
引数に取らん場合には class にしてる。まー、趣味の問題だね。
typename と class は全く同一だと聞いた事があるが・・・どこでだっけ?
本屋行ってみたが、洋書は置いてないと言われた。(´・ω・`)ショボーン
日本訳が出るまで最低1年はかかるからなー。
typename自体が無いしょぼーいコンパイラも世の中には存在する。
>196
まだ使ってるのか… 御愁傷様です。
>>194
全く同一だよ。だからみんなして趣味の問題とか個人的にはとか言ってるわけ。

>>195
出たばっかりの洋書はWebで買った方が良いと思う。
199デフォルトの名無しさん:02/12/05 20:14
VC6sp5にも移植が出来たみたいです
http://fara.cs.uni-potsdam.de/~kaufmann/?page=lokiport
boost::lexical_castで、スペースを含む文字列を変換すると例外が
出ますな。

std::cout << boost::lexical_cast<char*>(std::string("abc def")) << std::endl;
std::cout << boost::lexical_cast<std::string>("abc def") << std::endl;

boost::lexical_castはstd::stringstreamを使って実装しているので、
>>演算子や<<演算子がスペースを区切り文字とみなしてしまう故らしい。
何とかして欲しいですな。
>>201
http://groups.yahoo.com/group/boost/files/lexical_cast_proposition/
…では直ってるので1.30では修正が取り込まれると思いたい。
と言いながら結局1.29には取り込まれなかったけどなぁ。
203デフォルトの名無しさん:02/12/08 23:26
落ちそうなので一回ageます。
204デフォルトの名無しさん:02/12/09 00:24
昨日からSTLの勉強をVC++.Netで始めました。
まだ、わかってない部分が多いのですが、質問させてください。

汎用クラスを定義する際、通常のクラス定義のように CSample.h , CSample.cpp
のように宣言と定義を別ファイルにはできないのですか?

ウィザード利用によるクラス定義(一般クラスの作成手順)を行って、
後で、Template <class T> 文を
class CSample
宣言の前につけたり、いろいろしましたが、コンパイルが通りません。
(中間オブジェファイルができません)

結局、定義と宣言を分けないでヘッダファイルのみで全てを記述すれば、OKでした。

実際に汎用クラスを利用する際には、利用箇所によって型決定する事を考えれば
当然のような気もするんですが、そうなんでしょうか?

もしそうなら、複数のファイルで、同一の汎用クラスを利用する際は、利用するファイルに、
定義した汎用クラス全文をインクルードすることになるんでしょうか。
>>204
>複数のファイルで、同一の汎用クラスを利用する際は、
>利用するファイルに、定義した汎用クラス全文を
>インクルードすることになるんでしょうか
そうです
>>204
何度もガイシュツだが、exportキーワードを完全にサポートしている処理系
でなければ、template文の宣言と実体を別のファイルに分けて書くことはできない。

もしexportキーワードが有効であれば、実体部をライブラリにできることになる。
207204:02/12/09 00:44
やっぱりそうだったんですね。
しかも、ガイシュツとのことで、もうしわけないです。
ありがとうございました。がんばってみます。
物の本によれば、//1の書き方は正しくなく、//2のように書かなければならないと
いう意見があるのですが、どちらが正しいのでしょうか。
ちなみにコンパイルはどちらでも通ります(gcc3.2)。

struct Test {
template <typename T, typename U>
void func(T x, U y) {
std::cout << typeid(x).name() << ' ' << typeid(y).name() << std::endl;
}
};

int main()
{
Test t;
t.func(1, 1); // as <int, int>
t.func(1.1, 2.2); // as <double, double>
t.func<int, double>(2, 3.3); //1
t.template func<int, double>(2, 3.3); //2
}
>>208
メンバ関数テンプレートはtと同一のスコープの時は
大丈夫ですが、パラメータとしてtをどこかへ渡すと
t.template と書く必要があります。
>>209
大丈夫なようですが・・・・・意味を勘違いしてるかな?

struct Test {
template <typename T, typename U>
void func(T x, U y) {
std::cout << typeid(x).name() << ' ' << typeid(y).name() << std::endl;
}
};

void abc(Test& t)
{
t.func(1, 1.1);
}

int main()
{
Test t;

abc(t);
}
>>210
あんまり適当なことを言うのもあれなんで識者の人に
聞きたいところだけど、
基本的には型推論できるところは.templateは要らないと思った。
http://pc.2ch.net/tech/kako/1008/10085/1008593126.html
に書いてあったんだけど、900番台がなぜか抜けてるんだよね。。。

これ以上は分りません。すんまそん。
>>210
わざわざすみません。いろいろ実験してみたら、下のエラーとコメントしてある
行で、'<'がどうも比較演算子とコンパイラが勘違いしてエラーになるようです。

こういう場合、template限定子を付けて、後に続く'<'が型名のパラメータの
始まりである事を示さなければならないようです。

まだよくわかってないのですが、さらに実験してみます。

struct Test {
template <typename T, typename U>
T test(U x) {
std::cout << typeid(T).name() << ' ' << typeid(x).name() << std::endl;
return static_cast<T>(x);
}
};

template <typename T>
T abc(T x)
{
Test t;
T y;
// y = t.test<T>(x); // エラー
y = t.template test<T>(x);
return y;
}

int main()
{
abc(1.1);
}
スマソ>>211さんに対してのレスです。
>>212
それはコンパイラのバグだと思う…。

> template <typename T>
> T abc(T x)
> {
> Test t;
> T y;
> y = t.test<T>(x); // エラー

だと t の型はtemplateパラメータ T に依存せずに決定しているので、
わざわざ template 限定子を入れる必要はないはず。t の型が T に
依存するなら、test がメンバ関数 template であることはパース時には
わからんから、明示的な template 限定子が必要になるけれど。

例えばもし
> template <typename Y>
> struct Test {

> T abc(T x)
> {
> Test<T> t;
だったら、tの型がTに依存するので、必要。
215デフォルトの名無しさん:02/12/09 13:29
漢字のテクスチャを管理するデータ構造を作りたいです。
機能と優先順位は
1.内部で管理しているテクスチャのハンドル数が最大数を超えたら最も古いハンドルを開放する。
2.sjisのコードを指定するとデータ構造からテクスチャのハンドルを検索して返す。
3.ハンドルが存在しなければその時点でテクスチャを生成してそのハンドルを返す。
で、要素の構造体はこんな感じです。
struct{
unsigned short Code; /// 文字コード
void *Handle; /// テクスチャハンドル
};

要するにキャッシュの機構なんですがとりあえず
hashでインスタンスを、queueで参照を管理するというのを
思いついたんですが他に効率的な方法はありますか?
216bloom:02/12/09 13:40
>>214
いろいろやってみたけど、templateパラメータは現れた順に解決される
みたいですね。

コンパイラはgcc3.2(MinGW)を使ってみたんですけど、やっぱりバグです
かね。プログラミング言語C++第3版§C.13.6、P971を読んでいたら、メンバ
テンプレートの型の推定が不可能な場合、メンバ関数名の次に現れる
"<"を比較演算子と見なしてしまいコンパイルエラーになるような事が
書いてありました。

でもそのような事はまれなので、エラーが生じた場合のみtemplate限定子
を付けるようにしようと思います。
>>204
オソレスだが、次のようにするとVC7でも分割できる。

--- T.h ---
template <typename T>
void print(const T&);

--- T.cpp ---
#include <iostream>
#include "T.h"

template <typename T>
void print(const T& t)
{    std::cout << t << std::endl; }

template void print<int>(const int&);

--- main.cpp ---
#include "T.h"

int main()
{
   int i = 10;
   print(i);

   return 0;
}
> template void print<int>(const int&);

template にする意味あんまりないじゃん。
220204:02/12/09 22:40
>218
ありがとうございます。動きました。

この場合、T.cpp をコンパイルする際には、実際の利用時の型を T.cpp 内部で明確にし、
それぞれの型別動作をオブジェファイルに記述している。と考えていいんですよね。

main 部に { double d ; print d } を追加するとリンクできないが、
T.cpp に template void print<double>(const double&); を記述すると正常動作したので、
このように解釈しました。
>>219
たしかに、語源的な意味しか残ってないわな。

>>220
おおむね合ってます。「明示的なインスタンス化」っていうやつですわ。
ソースファイル

プレコンパイル

ソース内包オブジェクトファイル

リンク

ソース内包リンクドモジュール

ポストコンパイル

ロードモジュール

という方式にすれば、export 対応はそんなに難しくないと思うんだけど・・・。
>222
簡単に逆コンパイルできちゃうような代物だと、そもそも export 使う意味が無いと
思うんだが。速度の話なら pre compiled header って手もあるわけだし。
export って逆コンパイルと何か関係あるの?
225デフォルトの名無しさん:02/12/10 21:38


でさ、、、、

どれが一番速いの?
何の話?
どのライブラリが一番効率よいかってこと。

228デフォルトの名無しさん:02/12/10 21:49
STLport 4.5.3をVC6sp5で使おうと思ってインストールしたんですが、
BoundsCheckerがSTLportのアロケータ(たぶん)みたいなところで
メモリリークを検出してくれます。

#include <iostream>
#include <string>
int main(int argc, char* argv[])
{
  std::string hello = "Hello, world!";
  std::cout << hello << std::endl;
  return 0;
}
こんなコードでも1600バイトのリークが検出されます。
_STLP_USE_NEWALLOCマクロを使えば出なくなるんですが、遅くなりそうだなー
ってのと、Configuration Manualに

When using tools like Purify (c), Codeguard (c) or BoundsChecker (c),
it is advised to #define _STLP_USE_MALLOC or _STLP_USE_NEWALLOC,
otherwise pointer checking will generally not be available on most STL
internal structures, thus defeating the purpose of those tools.

とあるので気にしなくていいってことなんでしょうか?
>228
気にするな。
>>228

実際STLportのdefault allocatorは一度確保したら絶対返さない。

> とあるので気にしなくていいってことなんでしょうか?

時と場合で気にしたりしなかったり

allocatorつかったらmallocされっぱなしでも困らないならそのまま

返してくれなきゃ困る場合はSTLP_USE_MALLOCとか
自前でallocator用意すれ
231デフォルトの名無しさん:02/12/11 18:56
Effective STLなかなか良さげ
232学習能力の無い人:02/12/12 13:06
mapにconst reference operator[]() constって
何で無いの?
毎回const map作って[]使おうとすると怒られるから
constはずすってことをつい繰り返しちゃうんだけど・・・。
>>232
std::mapの[]演算子は、対応するキーがないと、自動的に挿入する仕様になって
いるから。その時点で既にconstでは無い。

[]が便利な事は認めるが、できるだけfindとinsertを使おう。例えばstd::multimapには
[]演算子が無い。仕様をよく考えると当然だが、最初この事を知ったとき、STLには
設計ミスがあるのではないかと思ってしまった。
対応するキーがないと自動的に挿入する、という機能が欲しい時に [] を使わない
理由があるの?
>234
効率。
>>235
コード量が増える割には、見合った効果が得られないけど?

初期要素 500,000、試行回数 5,000,000 で試してみた。
挿入が全く発生しない状況でも、1 % 程しか遅くならない。
挿入しか発生しない場合は 5 % 程遅い。

それとも、漏れの書き方が悪い?

int r = large_rand();
map<int, int>::iterator itr = m2.find(r);
if(itr == m2.end())
itr = m2.insert(pair<int, int>(r, 0)).first;
return itr->second;
つーか、233 の 「例えば」 の前後が繋がってないよ。
236のコードを見て気が付いたが、
find,insertではコピーコンストラクタが呼ばれて
[]演算子だとデフォルトコンストラクタが呼ばれた後に
=演算子が呼び出されるんだな。

だからintではなくもっと複雑な型じゃないと差は出ないのかも。

逆に、find,insertでは二回検索するので余計に遅くなりそうな気がするのだが
236の結果を見るとそうでもないのが不思議。
239237:02/12/13 18:00
>>238
> find,insertでは二回検索するので余計に遅くなりそうな気がするのだが

漏れも最初そう思ったけど、find が意外に速いんだよね。
ちなみに、[] の実装はこうだったよ。

_Tref operator[](const key_type& _Kv)
{
 iterator _P = insert(value_type(_Kv, _Ty())).first;
 return ((*_P).second);
}

つまり、236 のコードの、if より下と全く同等。
だから、テストでは find のミスヒット分だけ遅くなったという事だね。

> find,insertではコピーコンストラクタが呼ばれて
> []演算子だとデフォルトコンストラクタが呼ばれた後に
> =演算子が呼び出されるんだな。

上に示した通り共通の動作をしているので、これは違うと思う。
240238:02/12/13 20:30
スマソ、勘違いしてた。
何を思ったか[]演算子を使う方に

m2[r]=0;

みたいなコードを想像してた。
これじゃ動作が違うのに。
>>239
そんなタコな実装ねぇだろ。
その実装だと、
・二回検索することになる
・挿入しない場合にも一時オブジェクトの生成・破棄がおこなわれる。
242239:02/12/13 21:13
> そんなタコな実装ねぇだろ。

VC6 に付属の STL をそのままかっぱらってきたんだが・・・。
ところで、どこが 2 重検索になるって?
243241:02/12/13 22:42
ほんとだ>VC6
おそろしい。

あ、二回検索にはならねぇな。
236と脳内ブレンドされてたよ。スマソ
* Copyright (c) 1994
* Hewlett-Packard Company
だと、
Allocator<T>::reference operator[](const key_type& k) {
 return (*((insert(value_type(k, T()))).first)).second;
}
だな。
まぁ、なんだ。たしかに簡潔といえば簡潔だが……
std::mapのoperator[]は特異な存在だけど、便利であるがゆえによく使う。
コードがかさばってでも速い方がいいというなら、C++ を使う理由はない。
STLportのstd::bit_vectorと、Boostのboost::dynamic_bitsetの使い分けは
どのようにされていますか?
コードがかさばっても速さと汎用性が両立できるなら、C++を使う理由になる。
> 汎用性

何の話?
>249
スレの趣旨から言って Generic プログラミングだろう(違うか)
251デフォルトの名無しさん:02/12/15 23:10
vc++ver7.0でもtupleは使えない。ok?
252デフォルトの名無しさん:02/12/16 00:45
#include<string>
using namespace std;

template <typename T> struct dd :public T
{
typename typedef dd<T>::value_type char_type;
inline friend operator<(const dd<T>& a1,const dd<T>& a2 ); //(1)
inline friend operator<(const dd<T>& a1,const char_type* a2 );//(2)
dd(){}
~dd(){}
dd(const char_type* a){ *this=a;}
};

template <typename T> bool operator<(const dd<T>& a1,const dd<T>& a2 )
{
return ((const T&)a1 < (const T&)a2);
}

template <typename T> bool operator<(const dd<T>& a1, const dd<T>::char_type* a2 )
{
return ((const T&)a1 < a2);
}

int main()
{
dd<string> D("abc"),D2("efg");
D < D2; //(1) OK
D < "abc"; //(2) NG
}
templateのoperatorで
(2)のような場合、実装をクラスの中に書くしかないのでしょうか?
253デフォルトの名無しさん:02/12/16 01:04
修正:
dd(const char_type* a)
{
static_cast<T&>(*this)=a;
}
ですね。
追記:
friendなんだからクラス内に実装を書けということなのか、
friendの行を削除したらOKでした。
テンプレートクラスはfriendをメンバに取ることはできないね。
しまった、テンプレートクラスもfriendはメンバに取れるね。逝ってくる・・・
>>252>>253
うまくいったよ。ddのコンストラクタはexplicit宣言しておかないと、(1)や(2)で
勝手にstd::operator< が選ばれて警告が出る。

template <typename T>
struct dd : public T {
typedef T value_type;
typedef typename dd<T>::value_type char_type;
friend bool operator< <T>(const dd<T>& a1, const dd<T>& a2); //(1)
friend bool operator< <T>(const dd<T>& a1, const char_type* a2);//(2)
dd() {}
explicit dd(const char* a){
static_cast<T&>(*this) = a;
}
~dd() {}
};
template <typename T>
inline bool operator<(const dd<T>& a1,const dd<T>& a2)
{
return ((const T&)a1 < (const T&)a2);
}

template <typename T>
inline bool operator<(const dd<T>& a1, const typename dd<T>::char_type* a2)
{
return ((const T&)a1 < a2);
}

int main()
{
dd<std::string> D("abc"), D2("efg");
D < D2; //(1) OK
D < "abc"; //(2) OK
}

friend宣言で未解決のテンプレートパラメータがあると、非テンプレート関数として
コンパイルされてしまうらしいから、型特定して警告を回避した。
でもまだおかしいや。(2)が実行されてないようです。

template <typename T>
struct dd : public T {
typedef T value_type;
typedef typename dd<T>::value_type char_type;
friend bool operator< <T>(const dd<T>& a1, const dd<T>& a2); //(1)
friend bool operator< <T>(const dd<T>& a1, const typename dd<T>::char_type* a2);//(2)
dd() {}
explicit dd(const char* a){
static_cast<T&>(*this) = a;
}
~dd() {}
};
template <typename T>
inline bool operator<(const dd<T>& a1,const dd<T>& a2)
{
std::cout << "dd<T> < dd<T>" << std::endl;
return ((const T&)a1 < (const T&)a2);
}

template <typename T>
inline bool operator<(const dd<T>& a1, const typename dd<T>::char_type* a2)
{
std::cout << "dd<T> < dd<T>::char_type" << std::endl;
return ((const T&)a1 < a2);
}

int main()
{
dd<std::string> D("abc"), D2("efg");
D < D2; //(1) OK
D < "abc"; //(2) OK、しかし実行されない?
}
260デフォルトの名無しさん:02/12/16 05:05
>>259
基底クラス(std::string)の operator<(const std::string&, const char*) が
呼ばれているようだな
通常の関数とテンプレート関数が多重定義されている場合、通常の関数が
優先されるからな
261デフォルトの名無しさん:02/12/16 09:57
継承したクラスのオブジェクトは自分自身を指すのだね。
template <typename T> struct dd :public T
{
typedef typename dd<T>::value_type char_type;
friend bool operator<(const char_type* a1, const dd<T>& a2 )
{
cout << "(3) m_str ->"<< a2.m_str << endl;//何も表示されない!!
return (a1 < (const T&)a2);
}
dd(){m_str="2ch";}
~dd(){}
explicit dd(const char_type* a)
{
dd::dd();
static_cast<T&>(*this)=a;//なんとm_strにaが入る
}
private:
string m_str;
};
262続き:02/12/16 09:57
template <typename T> bool operator<(const dd<T>& a1,const dd<T>& a2 )
{
cout << "(1)" << endl;
return ((const T&)a1 < (const T&)a2);
}
template <typename T> bool operator<(const dd<T>& a1, const typename dd<T>::char_type* a2 )
{
cout << "(2)" << endl;
return ((const T&)a1 < a2);
}
int main()
{
dd<string> D("abc"),D2("efg");
D < D2; //(1) OK
D < "abc"; //(2) OK
"abc" < D; //(3) OK
}
>>261
>cout << "(3) m_str ->"<< a2.m_str << endl;//何も表示されない!!
m_str は初期化時の空文のままだから、表示されないのは当たり前。
>static_cast<T&>(*this)=a;//なんとm_strにaが入る
そんなわけね〜だろ!

なんか、バカでっかい勘違いしてんぞ

264引き篭もり:02/12/16 12:48
レベルたけぇ・・・(-_-)
int main()
{
dd<std::string> D("abc"), D2("efg");
D < D2; //(1) OK
D < std::string("abc";) //(2) OK
}

のように、sts::stringの一時変数を作って渡してやらないと、テンプレート関数
の方を呼んでくれない。この当たりがテンプレートの限界なのか。
しかし、ちょっと疑問なのだが、

explicit dd(const typename dd<T>::char_type& a){
static_cast<T&>(*this) = a;
}

これって一体どこに代入しているの?どうみても自分自身に代入しているように
しか見えないのだが・・・・・どんな意味があるのだろう。
基本的な質問です。
More Effective C++のp.16、l2に実際のプログラムでは、このようなクラスはテンプレートになるのだが、
とあります。具体的にはどのように書けばいいのでしょうか?
>>266
なんか激しく気持ち悪い書き方だなぁ。
*(static_cast<T*>(this)) = a;
あるいはすなおに
T::operator=(a);
と書いたほうがわかりやすくないかい?
>>267
たんに、要素の型を int きめうちじゃなくてテンプレート引数で
指定できるようにすべきだ、ってことじゃないの?
>>268
というか、素直にこうだろ〜
explicit dd(const typename dd<T>::char_type& a) : T(a) { }
266です。
>>268>>270 やっはりそうですよね。分かりやすく書くことを心がけるようにします。
272デフォルトの名無しさん:02/12/16 15:33
dd::dd();//このあとすぐにdd::~dd()が呼ばれてるみたい。
static_cast<T&>(*this)=a;//だからm_strは空白になってる。
なんかすごい勘違いしてたな。絶対変だと薄々思ってたけど...

コンストラクタからコンストラクタを呼ぶと直後にデストラクタが呼び出されるのか。

struct A :public string
{
string m_str;
A()
{
m_str="2ch";
cout << "A::A()" << endl;
}
~A()
{
cout << "A::~A()" << endl;
}
A(const char* c) :string(c)
{
A::A();
cout << "A::A(const char*)"<< endl;
}
};

int main()
{
A a("stu");
}


>>272
ちょっと違う。A::A(); と書くと、コンストラクタを呼び出したことにはならない。
単にAの一時変数が作成されてすぐに破棄されるだけ。

明示的にコンストラクタを呼び出すには、コンストラクタ初期化子を使う
しかない。
>A(const char* c) :string(c)
これ、: m_str(c) の間違いではなくて?
こういう書き方あるの?
275デフォルトの名無しさん:02/12/16 18:12
>>273
なるほど!

>>274
A は stringを継承して、メンバも持っているから...。

A(const char* c) :string(c),m_str("m_str")
{
cout << static_cast<string>(*this) << endl;//stu
cout << m_str << endl;//m_str
}
明示的に呼ぶ場合、
this->A::A();
これならOKなのでは?
>>276
エラーっしょ。
>>277
できるよ。


#include <iostream>

using namespace std;

struct clsA
{
clsA(){cout<<"clsA():"<<hex<<(unsigned int)this<<endl;}
clsA(int){cout<<"clsA(int):"<<hex<<(unsigned int)this<<endl;
cout<<"CASE:clsA::clsA()"<<endl;clsA::clsA();
cout<<"CASE:this->clsA::clsA()"<<endl;this->clsA::clsA();}
};

void main(void)
{
clsA a(int());
}
>>278
コンパイラは何を使った?Borland-C++5.6.2及びgcc3.2(MinGW)は
エラーが出て通らないけど。
280278:02/12/16 18:45
>>279
そうなの?
VC5(苦笑)でつ。
M$オンリーの機能なのか?
エラーはどんなの?
>>280
BCC5.6.2の場合。
エラー E2316 constructor2.cpp 12: 'clsA' は 'clsA' のメンバーではない(関数 clsA::clsA(int) )

gcc3.2(MinGW)の場合。
C:/MinGW/Learn/constructor2.cpp: In constructor `clsA::clsA(int)':
C:/MinGW/Learn/constructor2.cpp:12: parse error before `;' token

というエラーです。
282278:02/12/16 18:50
>>281
わざわざTHXです。
…う〜ん。いよいよM$の仕様のような気が。
参考書引っ張り出してもう一度調べてみマフ...
>>282
俺も調べてみるが、確かコンストラクタからコンストラクタを呼び出すには、
初期化リストしか方法がなかったように記憶しているが・・・・どうだったっけな
>>282
どっかのメーリングリストではVC固有の機能だと言われてたな。

>>283
ちょっと話は変わるけど、こんなのどう?

static_cast<T*>(this)->~T();
new(this)T(param);

newで例外が起きるとヤバイが。
>>284
newの配置構文ですね。この場合、デストラクタは自分で呼び出してやらないと
いけないですね。
>>285
だから直前に呼んでるみたいだが
>>285
そうか? 
この場合、Tは(*this) の型の基底クラスだろ
この型のデストラクタがデフォで ~T() 呼ぶから
大丈夫だと思うんだが、どうよ

>>286
ちょっと、目の付け所がいまいち
>>287
そっか。そう言われればそうだな。途中でリコンストラクトした事にはコンパイラ
は気づいてないだろうからね。
>>269 ありがd
>>284
× new(this)T(param);
○ new (static_cast<T*>(this)) T(param);
// こんな感じ?
#include <iostream>
using namespace std;

struct Base {
 Base() {
  cout << "Base::Base()" << endl;
 }
 virtual ~Base() {
  cout << "Base::~Base()" << endl;
 }
};

struct Ero : public Base {
 Ero() {
  cout << "エロ::エロ()" << endl;
 }
 ~Ero() {
  cout << "エロ::~エロ()" << endl;
 }
 Ero(int) {
  Base::~Base();
  new(this) Ero();
  cout << "エロ::エロ(int)" << endl;
 }
};

void main() {
 Ero ero(0); // エロ(0)
}
>>291
実行結果が次のようになったのだが、大丈夫だろうか?

Base::Base()
エロ::~エロ() //←これヤバくない?
Base::~Base()
Base::Base()
エロ::エロ()
エロ::エロ(int)
エロ::~エロ()
Base::~Base()
>>291
// ぜんぜん違うぞ、こうだ
#include <iostream>
class Foo
{
   int m;
public:
   Foo(int n = 0) : m(n)
   {   std::cout << "Foo is created by " << n << std::endl; }
   int val() const { return m; }
   ~Foo()
   {   std::cout << "Foo is destroyed. m = " << m << std::endl; }
};

template <typename T> class Bar : public T
{
public:
   Bar (int n = 0)
   {
       std::cout << "Bar is created by " << n << std::endl;
       static_cast<T*>(this)->~T();
       new (static_cast<T*>(this)) T(n);
   }
   ~Bar()
   {   std::cout << "Bar is destroyed." << std::endl; }
};

int main()
{
   Bar<Foo>(10);
}
294293:02/12/16 21:55
今気づいたが、
テンプレート使う必然性無く、まったくレス違いなネタのような……
>>293
ををををぉぉぉぉなんとトリッキーな。

Fooのインスタンスが先に生成されるのが意外だったけど、これは使えそうだね。
296291:02/12/16 22:03
>>292
やばいです。
つーか、うち(VC7)ではこうなりました。
仮想関数テーブルの取り出し方が違うのでしょうか?

Base::Base()
Base::~Base()
Base::Base()
エロ::エロ()
エロ::エロ(int)
エロ::~エロ()
Base::~Base()

>>293
飛び入りな者でスミマセン。
>>296
>>292はBorland-C++5.6.2です。
gcc3.2(MinGW)でやったら、次のようなエラーが出てコンパイルできませんでした。

C:/MinGW/Learn/constructor3.cpp: In constructor `Ero::Ero(int)':
C:/MinGW/Learn/constructor3.cpp:20: cannot call destructor `Base::~Base'
without object
gcc3.2(MinGW)は次のようにしたらコンパイルできて、実行結果は以下の通りです。

Ero(int) {
this->Base::~Base(); // thisから呼び出すようにした
new(this) Ero();
std::cout << "エロ::エロ(int)" << std::endl;
}

Base::Base()
Base::~Base()
Base::Base()
エロ::エロ()
エロ::エロ(int)

コンパイラによって実行結果がバラバラですね(^_^;)。
昨日から Modern C++ Design 読み始めたがなんだか
出じゃブーが多いなあ。
Phoenix Singleton とかな(藁
>>298
>コンパイラによって実行結果がバラバラですね(^_^;)。
データレイアウトの違いが原因かも(根拠なし)
>>300
300getしてるよ。
2〜3年前に似たようなこと頑張って考えてた時期あった。
基本型とユザ定義型の区別とか。
コンパイル時のじゃなくて実行時に区別するやつ。
ただしおれは目的があくまでパズルだった。
実用にしようと思ってたらなんか結果出てたかな...?
これって、メモリリークしちゃうの?
しないですよね?
void foo() {
    std::vector<std::string> v;
    v.push_back( *(new std::string("お兄ちゃん♥") );
}
Clear()
{
  for(std::vector<std::string>::iterator it=v.begin(); it!=v.end, ++it)
    delete &(*it);
  v.clear();
}

とかやらないと駄目なんじゃない?
>>304
(*it)はnewで作成したstringを
コピーコンストラクタでコピーした物だからダメだと思うが。
306303:02/12/18 12:48
>>304-305
えっと、つまり、
void foo() {
string* p;
std::vector<std::string> v;
v.push_back( *(p = new std::string("美幸...おまえ...") );
delete p;
}
ってやらなきゃだめ、ってことですか?
>>306
そのコードだと、↓といっしょだな。
void foo() {
std::vector<std::string> v;
v.push_back( "美幸...おまえ..." );
}
308303:02/12/19 09:26
うん、えっと、std::vectorが、
「なにを保持してるのか、どう扱えばいいのか」を知りたかっただけなのです。
そか、307見たいに書けるって事は、
「std::vector::push_backは、引数を基にして、
変換コンストラクタかコピーコンストラクタで新しいインスタンスを作って、
そのインスタンスを保持する」
ってことだよね。

新しいインスタンスを保持するんだから、
元のインスタンスは自分で解放する必要がある、と。

やっと心のもやもやが。ありがとうでした。
309デフォルトの名無しさん:02/12/19 09:48
「TIME」誌2002年の顔にアラファト議長を! 3
http://live.2ch.net/test/read.cgi/festival/1040234682/

急募!投票ツール作れる方
97式アラファトマシンガンが無効に!  
アラファトの票がリセット!
310デフォルトの名無しさん:02/12/19 12:49
次のコードがコンパイルできないんですけどなぜ?

#include <iostream>
template <class T>
struct Hoge
{
    friend void func()
    {   std::cout << "フレンド関数なんだけど" <<std::endl; }
};

int main()
{
    func();
}

VC7では、「error: C2065: 'func': 定義されていない識別子です」とおこられます。
#定義してあんだけどなあ〜
>>310
'func' なんてどこにも定義してないだろ。
しかし、310 の friend void func() は、どうやって呼べばいいんだ?
313310:02/12/19 13:36
>>311 >>312
func() はフレンド関数だから、グローバルスコープのはずですけど
template <class T> って書いてある奴の何がグローバルスコープなんだ?
template Hoge<int>;
int main()
{
func();
}
かな。ま、func() が何かHoge型の引数をとってくれないと無意味だわな。
ということで310はtemplateのインスタンス化について小一時間勉強すること。
#include <iostream>
template <class T>
struct Hoge
{
friend void func<T>()
};

template<class T> void func()
{ std::cout << "フレンド関数なんだけど" <<std::endl; }

こうするはず
318310:02/12/19 13:57
>>314
template <class T> はHoge に付いているんで、メンバじゃない func() には関係ないと思うけど。

>>315>>316
動きました。でもなぜ?
func() は普通の関数じゃないの? テンプレートじゃない普通の関数をインスタンス化?
> テンプレートじゃない普通の関数

どうしてそう思うのか訊きたいのだが
320316:02/12/19 14:03
だから規格書嫁って。
14.5.3
-5- When a function is defined in a friend function declaration in a class template, the function is defined at each instantiation of the class template.
321310:02/12/19 14:16
>>319
フレンド関数が func() が テンプレート Hoge のメンバじゃない、っていうのは正しいですよね。
Hoge のtemplate <class T> は、クラスそのものとメンバに対してしか影響せず、パラメータに依存しているわけでもない func() とはまったく関係ないはず。
func() 自体も関数テンプレートとして定義されているわけじゃない。

だから普通の関数だと思うんだけど。
322310:02/12/19 14:22
>> 316
へえ、普通の関数でも、個別にインスタンス化されるんだ。
勉強になりました。
でも、ということは、インスタンス化されるごとに同じ定義が再生産されることになるの?
それってやぱくない? 
って、VC7はHoge を複数インスタンス化してもエラーになんないな。大丈夫なのかな?
そのネタくさい物言いなんとかしてください。それにこれは
どっちかというと相談室の方でやる質問なのでは?
324310:02/12/19 14:47
>>323
>そのネタくさい物言いなんとかしてください。
それは正直、すまんかった。きおつけるよ
>それにこれはどっちかというと相談室の方でやる質問なのでは?
template がらみだから、こっちに投げたけど、こんどからはそうするよ。
タイトルは s/template/generics/ のほうがよかったかもね
関数テンプレートの関数のアドレスって取ることができないの?

template <typename T>
class Hoge {
T i;
public:
Hoge(T t) : i(t) {}
friend void func<>(Hoge<T>&);
};

template <typename T>
void func(Hoge<T>& t)
{
std::cout << "フレンド関数なんだけど" << std::endl;
std::cout << t.i << std::endl;
std::cout << reinterpret_cast<long>(&func) << std::endl;
}

int main()
{
Hoge<int> h(123);
Hoge<int> i(456);
func(h);
func(i);
}
>>326
質問内容と貼り付けるソースを対応させてくれ。
ソースがいろんな(たぶん余計な)要素を含みすぎて
何を答えて欲しいのかがイマイチつかめん。

そのソースでエラーになるんだったら、&func<T>かなー?
>>327
スマソ。いらない要素を除いて短くしました。まだエラーが出ます。
コンパイラはgcc3.2.1(MinGW)です。

template <typename T>
class Hoge {
friend void func<>(Hoge<T>&);
};

template <typename T>
void func(Hoge<T>& t)
{
std::cout << reinterpret_cast<long>(&func<T>) << std::endl; //エラー
}

int main()
{
Hoge<int> h;
Hoge<int> i;
func(h);
func(i);
}
さらに短くしました。friend宣言もクラス宣言も取ってしまいました。

template <typename T>
void func(T t)
{
std::cout << t << std::endl;
std::cout << reinterpret_cast<long>(&func<T>) << std::endl; //エラー
}

int main()
{
func<int>(1);
}
329です。自己解決しました。
テンプレート関数は、コンパイラから関数のオーバーロードと解釈されるようです。
従って、関数名を正しくキャストする事によりうまくコンパイルできました。

template <typename T>
void func(T t)
{
std::cout << t << std::endl;
std::cout << reinterpret_cast<long>(static_cast<void (*)(T)>(func)) << std::endl; //うまく行く
}

int main()
{
func<int>(1);
func<double>(1);
func<int>(2);
}
んーでも少し問題が。gcc3.2.1(MinGW)では通るものの、Borland-C++5.6.2では

エラー E2335 overload2.cpp 7: このコンテキストではオーバーロード 'func' が曖昧(関数 void func<int>(int) )
エラー E2335 overload2.cpp 7: このコンテキストではオーバーロード 'func' が曖昧(関数 void func<double>(double) )

と言われてしまいました。Borland-C++が糞なのか、それとも私が何か間違っているのか?
332デフォルトの名無しさん:02/12/20 19:03
Modern C++ Design を読んで疑問に思ったので質問します
8章のオブジェクトファクトリのRegisterコールバック関数の登録についてです。
ある具象クラスLine(: public Shape)のソースにおいて
const bool registered = ShapeFactory::Instance().Register( LINE, CreateLine );
としてシングルトンのファクトリに登録していますが、
これはファクトリがシングルトンの場合にしかつかえないと思うのです。
動的にファクトリを生成・利用する場合には、具象クラスの情報を一ヶ所にまとめた物がどこかに必ず必要になると思うのですが、
この認識は正しいでしょうか?
シングルトンではなく、ファクトリになんの変更も無しに新たな具象クラスを追加する方法があるのでしょうか?
VC.NETのSTLへの対応ってどんなもんなんですか?
VC6.0と同じ程度なんですか?
sort(v.begin(),v.end(),mem_fun_ref(&hoge::hoge)); ←こんなの通るの?
>>332
Factoryクラスのstaticメンバに情報を持つか、FactoryのFactoryに
情報をまとめるようにして、Factoryの生成をライブラリ側で管理するか、
フリー関数のオーバーロードで頑張るかすれば、一応何とか出来るのではないかと。

しかし、ファクトリがSingletonでないことが必要な場合なら、
各々のファクトリが勝手に情報共有してしまったらむしろ
困ると思うのだけど、具体的にどういう場合を想定してるん?

>>333
> mem_fun_ref(&hoge::hoge)
いやコンストラクタをmem_funに渡せる実装はなかなか少ないだろう。

men_fun1_refにしないでも大丈夫になってるか?という意味なら、VC.NET 2002 ならOK。
>>334
すいません、編集ミスです。<コンストラクタ
しかも、ペーストする場所を思いっきり間違えてました。
質問したいのは、これ(↓)でした。
find_if(v.begin(),v.end(),bind2nd(mem_fun_ref(&Hoge::hoge),HogeObject));

手元にg++用に書かれたコード(STL多用)があり、
これにGUI部分を実装しなければならないのですが、
VC6までは、STLがまともに動かないという話を聞いたことがあるので、
VC.NETではどうなってるのかなと思って質問しました。
やっぱり、BCB6の方が良いでしょうか?
336332:02/12/21 05:27
>>334
疑問に思っていたのは以下の2点でした
・「シングルトン」及び「staticメンバに情報を登録」ではプログラムロード時からメモリに存在する。
・ファクトリ側では実行するまでどんな具象クラスが登録されるかを知らない形にし、各具象クラスのcppファイルで登録させる。

プログラムの流れでたまにしか出てこない、いろんな種類のファクトリをはじめからメモリに確保するのが嫌だったのです。
でも実行時に登録するには、
・コンパイラが自動的に実行してくれるグローバルな領域に置かれた命令による登録(シングルトンが必要)
・どこかにリストアップしておく。
のどちらかしか無いように思います。
用語が滅茶苦茶だと思いますがすいません。
337sage:02/12/21 05:37
>・コンパイラが自動的に実行してくれるグローバルな領域に置かれた命令による登録(シングルトンが必要)
グローバルはおかしいかな。
cppファイルの頭の部分に書く
const bool registered = Singleton::Register(objType,CreateCallback);
な感じのやつのことです。
ファクトリの百や二百、メモリを使用してるうちに入らんと思える私は幸せなのでしょうか。
339332:02/12/21 09:26
私もです。しかもせいぜい10個くらい。
std::mem_fun_refってどういう時に使う?
std::mem_funは、仮想関数を呼び出す時に便利だが、std::mem_fun_refだと
クラスへのポインタではなく実体を渡さないといけないので、例えば

class A;
class B : public A;

のようになっているとして、

std::vector<A*> にはBへのポインタも格納できるが、std::vector<A>にBを
格納しようとすると未定義の動作となる。ポインタならばstd::mem_funで
呼び出せる。std::mem_fun_refは実体を渡さなければならないが、vector
に両方は格納できない。

だから、std::for_each()などで、std::mem_fun_refを使う状況というのがどう
いう場合なのか知りたい。
>>340
Aが派生して使うような型じゃない場合。
>>341
なるほど、こんな場合か。単純と言えば単純だな。

class A {
int j;
public:
void print(int i) {
std::cout << i + j << std::endl;
}
A(int k) : j(k) {}
};

int main()
{
std::vector<A> a;

a.push_back(A(1));
a.push_back(A(2));
a.push_back(A(3));

std::for_each(a.begin(), a.end(), std::bind2nd(std::mem_fun_ref(&A::print), 1));
}
boost::anyと、std::mem_fun_refを使って仮想関数を呼び出そうとしたが
なかなかうまく行かない。

int main()
{
std::vector<boost::any> a;

a.push_back(A());
a.push_back(B());

std::for_each(a.begin(), a.end(), std::bind2nd(std::bind1st(std::mem_fun_ref(&A::print), boost::any_cast<A&>(this)), 1)); // だめ
}
344デフォルトの名無しさん:02/12/22 05:02
どうしてany_castに失敗するのでしょうか?

struct A {
void print() {
std::cout << "A" << std::endl;
}
};
int main()
{
std::vector<boost::any> a;

a.push_back(A());
a.push_back(A());

std::vector<boost::any>::iterator pos = a.begin();
try {
for (; pos != a.end(); ++pos)
boost::any_cast<A>(a).print();
}
catch (boost::bad_any_cast& e) {
std::cerr << e.what() << std::endl;
}
}
>>343
試さずに書いてるが、
boost::compose_f_gx( boost::bind( &A::print, _1, 1 ), &boost::any_cast<A&> );

>>344
boost::any_cast<A>(*pos).print();
じゃねーの?
346345:02/12/22 08:54
というか、今のバージョンのany_castって継承関係の把握できたっけ。
347デフォルトの名無しさん:02/12/22 09:49
Lokiのインストール法、誰か教えて。
英語読めん。
それと、iostreamをインストールすると、コンパイラ付属のは使えなくなるんか。
それはそれで不安だ。教えてくれ。
>>347
DLして解凍して適当なフォルダに入れてインクルードパス通すだけ
というかあれくらいの長さのreadmeくらい読みなよ…

後環境も何も書いてないからこれ以上は無理
349デフォルトの名無しさん:02/12/22 11:45
Lindows
>>345
ありがとうございます!

boost::compose_f_gx( boost::bind( &A::print, _1, 1 ), &boost::any_cast<A&> );
は通りませんでしたが、

boost::any_cast<A>(*pos).print();
は無事通りました。

boost::any_castは依存関係の把握はできないかもしれませんので、ポリモルフィズム
には使わないようにします。
352名無しさん@Emacs:02/12/22 23:47
げ、ホントだ、any_cast ってポリモーフィズムに使えないんだ・・・
っつーか皆さん boost::any ってどんな時に使ってます?
イチイチ any_cast 噛まさにゃならん上にポリモーフィズム使えないもの
をどんな風に使うのか興味があるのですが・・・
# つまり馬鹿だから使い道が思い付かないわけでして。

struct A { virtual void print() { std::cout << "A" << std::endl; }};

struct B : public A{ virtual void print() { std::cout << "B" << std::endl; }};

int main()
{
std::vector<boost::any> a;

a.push_back(new A());
a.push_back(new B());

std::vector<boost::any>::iterator pos = a.begin();
try {
for (; pos != a.end(); ++pos) boost::any_cast<A*>(*pos)->print();
}
catch (boost::bad_any_cast& e) {
std::cerr << e.what() << std::endl;
}
}

output>
A
boost::bad_any_cast: failed conversion using boost::any_cast
>>352
void* で汎用パラメータ渡し…とか、union でノードの種類を区別した
木構造…とかのtypesafeなバージョンとしては、とりあえず超高速で
お手軽に書こう、と思ったときには使えるかも。俺は使ったこと無いけど。

using namespace boost;
struct add { add(any l,any r):left(l),right(r){} any left, right; };
struct mul { mul(any l,any r):left(l),right(r){} any left, right; };

double eval_expr( any e )
{
if( e.type() == typeid(add) ) {
add ex = any_cast<add>(e);
return eval_expr( ex.left ) + eval_expr( ex.right );
} else if( e.type() == typeid(mul) ) {
mul ex = any_cast<mul>(e);
return eval_expr( ex.left ) * eval_expr( ex.right );
} else if( e.type() == typeid(double) ) {
return any_cast<double>(e);
} return any_cast<int>(e);
}

int main()
{
any expr = add( add(mul(6,7),2), mul(3,4) );
cout << eval_expr( expr ) << endl;
}

その手の使い方をするにしても、入れられる型に制限をつけた
variantとかの方がマシだしなぁ。
>>351
any.hppの中身を見てみると、boost::any_castはキャストしようとする型と、
元のタイプのtypeidを比較して、一致しないとキャストしないようになっている。
だからポリモルフィズムに使えないんだろう。

-- any.hpp (STLpotrt)より

template<typename ValueType>
ValueType * any_cast(any * operand)
{
return operand && operand->type() == typeid(ValueType)
? &static_cast<any::holder<ValueType> *>(operand->content)->held
: 0;
}

std::mem_fun_refと組み合わせていろいろと面白い事をやらせようとしていた
のだが、使えねー。まあだめならだめで昨日から悩み続けていた事が解決
したのでいいのだが。
スマソ>>354>>352さんに対するレスです。
すごく簡単な所でつまづいています。どこがおかしいのでしょうか?

class A {
public:
void func(int i) {
std::cout << i << std::endl;
}
};

int main()
{
std::vector<A> a;

a.push_back(A());
a.push_back(A());

std::for_each(a.begin(), a.end(), std::compose1(std::mem_fun_ref(&A::func), 1);
}
自己解決しました。うーん?直感的にはcompose1のような気がするのですが?
わからなくなってきた。

class A {
public:
void func(int i) {
std::cout << i << std::endl;
}
};

int main()
{
std::vector<A> a;

a.push_back(A());
a.push_back(A());

std::for_each(a.begin(), a.end(), std::bind2nd(std::mem_fun_ref(&A::func), 1));
}
358デフォルトの名無しさん:02/12/23 05:26
こんな簡単なプログラムがコンパイルできません。どこがおかしいのか
わかりますか?コンパイラはgcc3.2.1です。

int main()
{
double ad[] = {0.5, 1.0, 1.5};
std::vector<double> d(ad, ad + 3);

std::transform(d.begin(), d.end(), std::ostream_iterator<double>(std::cout, " "), std::sin);
}
358です。非常に不本意ながら、自己解決しました。
#include <cmath>を#include <math.h>にして、std::sinをsinにすれば通ります。

しかし、ここで当然疑問が沸きます。なぜstd名前空間に包まれているsinが
std::transformに適用できないのか、どうしてもわかりません。何のための
<cmath>なんでしょうか?
>>356-357
compose1 というのは、返値を h = compose1( f, g ) とすると
h(x) が f( g(x) ) と同じ意味になる合成のことなわけだが。
たぶん貴方の場合、std::mem_fun_ref(&A::func) が2変数関数だし、
1 というのは関数ですらないので全然ダメ。

ついでに1変数メンバ関数用の mem_fun_ref は g = mem_fun_ref( f ) とすると
g(x, y) と x.*f(y) が同じ意味になるもので
bind2nd というのは g = bind2nd( f, c ) とすると
g( x ) が f( x, c ) と同じ意味になるものなので期待通りになる。
>>359
C では double sin(double x); しかないが、C++ では
double sin(double x);
float sin(float x);
long double sin(long double x);
とオーバーロードされてて、どれかわからんので困ってるのでは?
>>361
なるほどありがとうございます。キャストしたら通りました。引数が
doubleだからつい自動判別してくれると期待していたのですが、
アルゴリズム中では正しく働かないようですね。

int main()
{
double ad[] = {0.5, 1.0, 1.5};
std::vector<double> d(ad, ad + 3);

std::transform(d.begin(), d.end(), d.begin(), static_cast<double (*)(double)>(std::sin));
}
363デフォルトの名無しさん:02/12/23 19:22
typedef struct
{
int id;
double value;
} BANK;

std::list<BANK> blist;

みたいなlistがあって、こいつを構造体BANKの中のvalueの値で
sortしたい(valueの値が大きい順に)場合、どうしたらよいのでしょうか?
blist.sort()を使う方を教えてください!!
>>363
sortに引数を渡せ。
365352:02/12/23 19:27
>>353,354
むむむ、なるほど。情報サンクスコ
なんか大抵の場合はポリモーフィズムかテンプレート使えばいい感じですなぁ・・・
>>853氏の例をちょっといぢってみたんだけど、 6 を 6.0f にするだけで氏ぬのね。
typeid 使うとこの辺(double, float とかポリモーフィズムとか)が問題になって来るわけか。
なるほど、なるほど。勉強になりますた。
366デフォルトの名無しさん:02/12/23 19:38
>>364
引数の書き方がわからないです。教えてくらはい。
>>366
よーし、SGIのとこからもってきてやったぞ、ホレ。

template<class BinaryPredicate>
void sort(BinaryPredicate comp);

Comp must be a comparison function that induces a strict weak ordering (as defined in the LessThan Comparable requirements on objects of type T.
This function sorts the list *this according to Comp.
The sort is stable, that is, the relative order of equivalent elements is preserved.
All iterators remain valid and continue to point to the same elements.
The number of comparisons is approximately N log N, where N is the list's size.
>>366

struct BANK {
int id;
double value;
BANK(int i, double d) : id(i), value(d) {}
};

inline bool Cmp(BANK a, BANK b)
{
return a.value > b.value;
}

int main()
{
std::list<BANK> blist;

blist.push_back(BANK(1, 1.1));
blist.push_back(BANK(2, 3.3));
blist.push_back(BANK(3, 2.2));

blist.sort(Cmp);

std::list<BANK>::iterator pos = blist.begin();
while (pos != blist.end())
std::cout << pos->id << ", " << pos++->value << std::endl;
}
369デフォルトの名無しさん:02/12/23 20:03
363、366です。
わかりました!!
これで明日のミーティングに間に合いそうです。
みなさんありがとうございました。
C++のSTLには、叙述関数と関数オブジェクトの2種類があって、互いに
よく似ているために未だに混同します。

例えば関数オブジェクトは内部状態を持っていてそれを変化させても
いいようですが、叙述関数は呼び出しの度に内部状態を変化させては
ならないと規定されているようです。

皆さんはどうやって区別していますか?
370です。(゚Д゚)ハァ?なことを書いてしまってすみません。

叙述関数は、ブール値を返す関数または関数オブジェクトでした。
で、やっぱり関数オブジェクトも内部状態を変化させない方がいいの
でしょうか?
> 呼び出しの度に内部状態を変化させてはならないと規定
これどこで規定されてんの?
>>372
「規定」と書くと語弊がありますね。C++標準ライブラリ日本語版§8.1.4、P297
に「叙述関数と関数オブジェクトの違い」という節があり、内部状態を変化させ
る関数オブジェクトを叙述関数として使うと、予想に反した動作をする例が書か
れています。

つまり、constな関数オブジェクトでないと、予想した動作ではなくなる可能性
があるという事ですね。
>>373
その記述がすべてだな。「可能性がある」ってんだから、
あとは、場合による、としか言えないんじゃないの。
>>374
簡単にまとめると次のようになりますかね。

叙述関数:
  bool値を返す関数または関数オブジェクト。但し、呼び出し毎に内部状態
  が変化する関数または関数オブジェクトは、標準アルゴリズムに適用する
  と予想に反した動きをする可能性があるので、できるだけ使用しない方が良い。
>>375
まとめるのは勝手だが、
「可能性があるので」が理由じゃぁまとまってるとは言い難い。
>>376
やっぱり「可能性」の具体例をあげないとダメか・・・・
本を読んでくれ、なら簡単なんだが、自分でまとめるとなると、何か例を
考えないといけないか。
関数を提供する側から言えば、
副作用がない、と仮定してアルゴリズムが書かれていると、
述語(ここで言えば叙述関数)を呼び出す回数が予想できないわけだ。

副作用がないなら同じ引数で何度呼んでも値は同じはずだから、アルゴリズムは返り値をメモり、以降その値を使いまわすかもしれない。
(しかし副作用がある関数は呼ばれるごとに値が変わることができるから、メモった値と呼んで帰った値は一致しない可能性がある。)
このような性質はアルゴリズム内に隠蔽されていて関数提供側ではまったく予想できない。

一方、逆に標準アルゴリズムを提供する側から言えば、
述語は条件判定に使う関数だから、
例えば副作用がコンテナ内の要素に影響を及ぼす類のものだとすると結果は破壊的になりうるし、そうでなくても同じ対象を比較する際に呼び出すごとに違った値を返すとすると
それらを仮定してアルゴリズムを書くのは大変困難だ。

ひどい例を考えてみる。あるコンテナをソートするとする。
そのときにソートの比較に使う述語(if文の中で比較・判別に使われる)が
大小判定ついでにコンテナの値を書き換えるとすると、
どんなアルゴリズムでも大前提(ソート中に値が変化しない)が崩れるから
ソートはまずまともに機能しないだろう。
(終わらなくなったり、正しくない結果を返したり・・・。)

述語というのは論理学用語だが、
基本的にif文(あるいはfor文など)の条件式内で条件判定に使われる
特殊な種類の関数をさす用語。
普通、if文の中で代入や入出力などするコードはあまりお行儀が良いとは言えない
分かりにくい保守・変更しにくいコードだという事は納得してもらえると思う。それと同じ。
(エラー処理のように条件が成立したら処理を中止するような場合はともかく。)

一方、述語(叙述関数)は関数オブジェクトの中でも特殊なものなので、
一般の関数オブジェクトの在り様まで規制するものではないから、一般の関数オブジェクトは副作用があっても良い。っつーか、むしろないと困るものもあるくらいだろう。
379デフォルトの名無しさん:02/12/24 09:20
map のコンストラクタで、比較オブジェクトを引数にとるものがあるが、
それの存在意義がわからない。

プログラミング言語C++ 第3版 17.4.1.5
void f(map<string,int>& m)
{
  map<string,int> m2; // デフォルトで < を使う
  map<string,int> m3(m.key_comp()); // mの比較基準を使う
}

とあるが、m.key_comp() は less<string> だから、
デフォルトの < を使うのと同じこと。
比較オブジェクトをコンストラタに渡すのが有意義な場合ってある?
>>379
キーが整数として、比較基準を、ある基準値との差の比較とすると、
比較オブジェクトの中に基準値を入れて使うことが想定できる。

struct compare_distance
{
  const int origin;
  compare_distance(int org):origin(org){}
  bool operator() (int rhs, int lhs) const
  {
    return std::abs(rhs - origin) < std::abs(lhs - origin);
  }
};
381デフォルトの名無しさん:02/12/24 09:53
>>380 なるほどね。そういう例はわかります。その比較オブジェクトを渡す
mapの型は map<int, T, compare_distance> ですよね。
map<int, T> つまり map<int, T, less<int> > に、渡せるわけではないと。
これこそ型志向言語の神髄中の神髄、C++が最晩年に到達した
何にも真似のできない世界です。このライブラリに込められた
テンプレートの技法は、後世のどの言語もついに超えることが
ありませんでした。ですから現在でもこのライブラリはテンプ
レートの最高の技術を示した作品であり続けています。
C++の晩年には、テンプレートを駆使した手法は時代遅れとなっ
ており、手厳しい非難の対象にもなっていました。しかしC++は
テンプレートを捨てることなく、むしろテンプレートの限界を
極めるような作品を数多く生むようになります。その最高の成
果が、この「Loki」で、たった1つの主題の技法の可能性を徹
底的に汲み尽くした(残念ながらC++の死によって未完となって
いますが)作品となっています。加えて、ソースにコンパイラ
の指定がなく、そのためにVC++版、g++版、Comeau版など、いろ
いろでコンパイラに実装が試されています
>383 バッハの『フーガの技法』の解説のパクリかい?
>384 よく知ってるね
おれの中では両者の間に連想がある。なんというか厳格さと
柔軟さの混在というか...
でももしC++が廃れるようなことがあれば、テンプレートを
魔術的に駆使したものはフーガの技法みたいな扱いを受けそう。
過去の難解言語で為された魔術が
今どういう扱いを受けているか考えてみるといい
387デフォルトの名無しさん:02/12/25 15:00
最近知ったのですが、boost面白そうですねぇ。
俺の場合、STLとかからちゃんと勉強しないといけないけど(笑)

ところで、boostのfunctionalとかfunctionって、メンバ関数に対しても使えるの??
388デフォルトの名無しさん:02/12/25 16:44
STLはスレッドセーフですか?そうでないとしたらスレッドセーフなコンテナはありますか?
↑よく知らないけど純粋にテンプレートだけじゃないんですか???
390デフォルトの名無しさん:02/12/25 19:18
>>388
「このコンテナはスレッドセーフである」と規格に書かれてたりは、しないと思う(たぶん)。実装に依存すると考えるべきではないかなぁ?
Effective STL の Item 12 が "Have realistic expectations about the thread
safety of STL containers." となっているのでこれを読んでみては?
>>387
メンバ関数は第一引数にインスタンスのポインタを
渡してやればいいから、こんな感じ。
#include <iostream>
#include "boost/function.hpp"
#include "boost/bind.hpp"
struct Test {
int t_;
Test(int t) : t_(t) {}
int Add(char t) {return t_ + t;}
};
int main() {
Test test(5);
boost::function1<int, char> func;
func = boost::bind(&Test::Add, &test, _1);
boost::function2<int, Test *, char> func2;
func2 = &Test::Add;
std::cout << (func)(6) << std::endl;
std::cout << (func2)(&test, 6) << std::endl;
}
393デフォルトの名無しさん:02/12/29 16:46
Boost!

ワル カコイイ(・∀・)!
boost::formatの戻り値をchar*として受け取ってメッセージボックスに
表示したいのですがいい方法は無いですか?
()でくくってc_str()とかやってみましたが、
error C2039: 'c_str' : 'boost::basic_format<Ch,Tr>' のメンバではありません。
[
Ch=char,
Tr=std::char_traits<char>
]
と怒られてしまいます。

MessageBox(NULL, (boost::format("Error !!!\n"
"\tlocation %d:%d\n"
"\tcode %02x:%02x:%02x:%02x\n"
"\tmessage %s\n") %
parse_error->get_line() %
parse_error->get_row() %
parse_error->get_genre() %
parse_error->get_category() %
parse_error->get_sequence() %
parse_error->get_sequence_case() %
parse_error->get_message()).c_str(),
"error", 0);
(...).str().c_str() しかないんでない?
396393:02/12/29 21:54
SGIには感動した!
精子出た!
ropeキター
Modern C++ Designの19ページの一番下に紹介されてる
「極めて洒落たテクニック」のソースきぼーん
"Sutter"とか"copy constructor"とかで検索したけど
みつからんかった...
>>397
Exceptional C++ の項目13。
>>397
Loki::SmartPtr::operator=()を見たらいいやんって書いてあるやん。
400デフォルトの名無しさん:02/12/30 15:40
boost使うとコンパイル劇遅で、ノートな私はVCが死んだかと
思ってしまいます。
コンパイルを早くする方法ってないのかな?
templateだからやっぱ無理?
>>400
プリコンパイル
402デフォルトの名無しさん:02/12/30 17:33
>>401
「プリコンパイルヘッダの使用」とかいうやつ?
gcc-3.6ぐらいにはpchブランチの成果が取り込まれるといいな
>>402
ttp://www1.kcn.ne.jp/~robe/cpphtml/html03/cpp03003.html

この辺が参考になると思う。
GenScaterHierarchyについてわからない点。

template <class T1, class T2, template <class> class Unit>
class GenScaterHierarchy<TypeList<T1, T2>, Unit>
: public GenScatterHierarchy<T1, Unit>
: public GenScatterHierarchy<T2, Unit>
{
・・・・・
};

最初の(左側の)基底クラスはGenScatterHierarchy<T1, Unit>としなくても、

template <class T1, class T2, template <class> class Unit>
class GenScaterHierarchy<TypeList<T1, T2>, Unit>
: public Unit<T1>
: public GenScatterHierarchy<T2, Unit>
{
・・・・・
};

のようにUnit<T1>でいいのでは?
406デフォルトの名無しさん:03/01/06 02:49
保守
>>405
それだと継承ツリーの途中で Unit<T1> を複数回継承することになって、
コンパイルエラー食らわん?
>>407
そ、そうかな... ;
何かネタない?
http://groups.yahoo.com/group/boost/files/utf/
暇ならこれチェックして
411デフォルトの名無しさん:03/01/06 21:02
std::map<int, std::string>に値を挿入するには、

insert(std::map<int, std::string>::value_type(1, "abc"))

insert(std::pair<int, std::string>(1, "abc"))
のどちらがより適切でしょうか?
>>411
同じ。mapのvalue_typeは、pairをtypedefしたもの。
>>412
それはわかってるんじゃないか?
>>413
Borland-C++5.6.2でコンパイルしてみた所、同じようなコードを吐いているようです。
コンパイラが違うとバイナリも違ってくるかもしれませんが。
ただ、タイプ量が少ないstd::pairの方が多用される傾向にあると思います。

もっともmap<int, std::string>をtypedefして使えばどちらもあまり変わらないですね。
>>411
insert(std::make_pair(1, "abc"))
416デフォルトの名無しさん:03/01/08 14:25
std::wifstream win("in.txt");
std::wofstream wout("out.txt");
wout << win.rdbuf();
wout.close();
win.close();

マルチバイトを使おうとおもってテストでこれやってみたのですが、
0x81で始まる、日本語がうまく表示されないんですけど
ベターな解決策おしえてください。

win2000 vc6 stlport使用 です。
>>415
411です。
遅くなりましたがありがとうございます。make_pairという述語があるのですね。
>>416
stlに関係ないじゃん。(V)C++スレにゆくべきかと。
ちなみにマルチバイトとwchar_tは別物。
419デフォルトの名無しさん:03/01/08 16:59
1)string str="hoge";vector<string> vec;
2)vec.push_back(str);
3)str="fuga";

ここで2)でvectorに追加されているのはstrそのものでしょうか
あるいはそのコピーでしょうか?
また3)では2)でvectorに登録された内容は上書きされてしまうのでしょうか
>>419
当然コピーです。3)で代入しても、vectorの中身には何の影響も及ぼしません。
421419:03/01/08 17:07
>420
ありがとうございます。いろいろ試してみます
422416:03/01/08 18:13
>>418
そっかー、そりはショック。
首つって、VCスレいってきます。
ありがとございました。
423IP記録実験:03/01/08 21:28
IP記録実験
http://qb.2ch.net/test/read.cgi/accuse/1042013605/

1 名前:ひろゆき ◆3SHRUNYAXA @どうやら管理人 ★ 投稿日:03/01/08 17:13 ID:???
そんなわけで、qbサーバでIPの記録実験をはじめましたー。

27 名前:心得をよく読みましょう 投稿日:03/01/08 17:20 ID:yL/kYdMc
SETTING.TXT管轄でないということは全鯖導入を視野に、か?

38 名前:ひろゆき ◆3SHRUNYAXA 投稿日:03/01/08 17:22 ID:rLfxQ17l
>>27
鋭いです。

73 名前:ひろゆき ◆3SHRUNYAXA 投稿日:03/01/08 17:27 ID:rLfxQ17l
>ところで、IPが抜かれて何か今までと変わることってあるのでしょうか?
・今までより、サーバが重くなる。
・裁判所や警察からの照会があった場合にはIPを提出することがある。
424デフォルトの名無しさん:03/01/08 22:29
保守
>>1=無職
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
>>296
確かに民放じゃやらないですな。
BSではたまにやるけど。
>>405
またポリタンコですか
あいつどうしようもないですね。
あ、どーしてもいいたかったんだけど、

  絶 対 に 有 料 化 し な い で ね 。
429IP記録実験:03/01/09 01:59
IP記録実験
http://qb.2ch.net/test/read.cgi/accuse/1042013605/

1 名前:ひろゆき ◆3SHRUNYAXA @どうやら管理人 ★ 投稿日:03/01/08 17:13 ID:???
そんなわけで、qbサーバでIPの記録実験をはじめましたー。

27 名前:心得をよく読みましょう 投稿日:03/01/08 17:20 ID:yL/kYdMc
SETTING.TXT管轄でないということは全鯖導入を視野に、か?

38 名前:ひろゆき ◆3SHRUNYAXA 投稿日:03/01/08 17:22 ID:rLfxQ17l
>>27
鋭いです。

73 名前:ひろゆき ◆3SHRUNYAXA 投稿日:03/01/08 17:27 ID:rLfxQ17l
>ところで、IPが抜かれて何か今までと変わることってあるのでしょうか?
・今までより、サーバが重くなる。
・裁判所や警察からの照会があった場合にはIPを提出することがある。
>>638
そのキャップだけはいろんな意味で許せん。僕によこせ
>>56
Jane使えば一目瞭然
匿名匿名掲示板自体にクレームがついたんだから2chじゃ出来ないでしょ。。。




連続書き込み規制変えたな

きつい。。。
暴力団に殺人依頼した。管理人を入廷時に射殺する
434デフォルトの名無しさん:03/01/09 16:28
age
======2==C==H======================================================

         2ちゃんねるのお勧めな話題と
     ネットでの面白い出来事を配送したいと思ってます。。。

===============================読者数: 138720人 発行日:2003/1/9

年末年始ボケがそろそろ収まり始めた今日このごろのひろゆきです。

そんなわけで、年末に予告したIP記録ですが実験を開始しています。

「2ちゃんねる20030107」
こんな感じで各掲示板の最下部に日付が入ってるんですが、
20030107以降になってるところはログ記録実験中ですー。

んじゃ!

────────────────────────Age2ch─
■この書き込みは、Age2chを使って配信されています。
────────────────────────────
Keep your thread alive !
http://pc3.2ch.net/test/read.cgi/software/1041952901/l50
────────────────────────────
>>773-774
迂闊にもワラタ
>>589
ちょっと違うが今までがそんな感じだったんよ。
「(善意であろうが悪意であろうが)確認できない以上利用者が真偽を判断すべきであり、
要請があっただけで全て削除するべきではない。」
というのがひろゆきの主張。
嘘を嘘と〜の名言もこれに繋がる。

これに対して動物病院訴訟における地裁・高裁の判断は、
「外部から確認できない以上当事者が中傷だと主張し削除の要請をした場合は、管理人は削除すべき。」

今後はこれに倣い当事者側が中傷だと主張さえすればIP公開する必要が出るかもしれない。
(もちろん警察なり裁判所の正式な提出要請があってからになるだろうけど)
なお、書き込んだ者はその書き込みに対し責任を負うべし、ってのは賛成だが。
いずれにしろ善意の告発は難しくなると思われ。
>>104
と思うんだけど、某○○さんは違うという。。。
>>104
と思うんだけど、某○○さんは違うという。。。
>内容証明が届いて、すぐに削除したら、賠償はしなくていい気が。

それはそのとおりでしょうねぇ。

・内容証明が届いて、名誉毀損の書き込みがあることを知りえた
・その日から起算してン日間書き込みを消さなかった
・その間のン日間は名誉が毀損されたことによって被害が発生した
ということを「裁判所が認めれば」負けちゃうんじゃないかなぁ、、

>んだったら、IP取ってない板で、自分で自分を中傷して、
>すぐに裁判すれば賠償金が取れるってことになっちゃう、、

そのとおりじゃないすかねぇ、、
掲示板の持ち主がけんすうさんだという前提でいうと、
その中傷発言が自作自演かどうか、けんすうさんにも判断できないん
だったら、けんすうさんが責任を負わないといけないという判決ですよね。
しかし個人の中傷発言だったら最初から消せばいいのでは。。
ガイドライン読めないのに獣医になれる世の中・・・
2ちゃんねるに近いあるインターネット関連会社の社長は、
2ちゃんねるの幹部から得た話として証言する。
「2ちゃんねるは、運営者や幹部などが
それぞれ別々に会社を作りカネの流れを見え難くしているが、
実際の資金源は複数の大手通信会社系からの調査費名目のカネ。
月額で計約700万円と言い、年間にすれば1億円近く。
額はともあれ、これは通信会社系的には、
ぼう大なトラフィックを調査すると言う表向きの理由が一応は立つ。
自社系に都合の悪い書き込みがされた時に優先的に削除してもらうことも期待している」と前置きし
「通信会社系の削除の期待も含めて、2ちゃんねるは総会屋と同じになっている」と言うのだ。
IPでも記録されてみるか。
>>540
鑑定スレでお願いしようとして誤爆し・ま・す・た・!   
C++にevalが仕様として盛り込まれるのは何年ぐらいでしょうか?
ぼらんちあさんにお年玉です。
( ´∀`)ノ~●●●●
447デフォルトの名無しさん:03/01/10 15:36
>>445
cbrtが標準math functionsに組み込まれてから10年は必要です。
名前(アルファベット)五人分入力
         ↓
     辞書式に並び替える
         ↓
  "meido.doc"ファイルに書き込む
というプログラムを教えてください。
まじ困ってます。
>>441
2ちゃんねらでもPGなれるんだもん・・・。
糞だね。


今後、予想されるレス

「IPって何ですか?」

「串って何ですか?」 「串揚げ」

第3者が見て情報価値の低い書きこみ>「質の低い」
匿名性に絡む問題なので反対 28% 1193 票
サイトのためになるから賛成 54% 2315 票
利用しないから関係ない 8% 378 票
2ちゃんねるってなに? 4% 172 票
アクセスログってなに? 4% 173 票



そーいや boost::shared_ptr が policy 使うよーになるとか
ならんとかって話はどーなった?
君がそれやればなんとかなるかも(^_^;)
ますます、ファンタスティックでスリリングでドラマティックなスレッドですわね、
713 名前:ひろゆき ◆3SHRUNYAXA 投稿日:03/01/09 15:33 ID:Jx8vAdAb
というわけで、掲示板の最下部のバージョン表示が20030107a以降のやつは、
ログとり実験やってますです。
今のところ、qb,live2,tmpですね

722 名前:心得をよく読みましょう 投稿日:03/01/09 15:43 ID:b1s0ydcx
qb : 2ch批判要望 削除議論 削除要請 削除整理
live2 : ニュース速報
tmp : ニュース極東 ちくり裏事情 政治思想 Download
    厨房! 人権問題 バカニュース 薬・違法
    ゴーマニズム ロビー 最悪 少年犯罪
    違反の潰し方 ペット苦手 なんでもあり 学歴

IP記録実験PART2
http://qb.2ch.net/test/read.cgi/accuse/1042020193/
======2==C==H======================================================

         2ちゃんねるのお勧めな話題と
     ネットでの面白い出来事を配送したいと思ってます。。。

===============================読者数: 139038人 発行日:2003/1/10

なにやら、連日メルマガだしてるひろゆきです。

そんなわけで、ログ記録実験ですが、いちいちサーバ指定するのが面倒なので、
全部のサーバに入れてみました。

重くなって落ちたりしてもご愛嬌ってことで。。。

んじゃ!

────────────────────────Age2ch─
■この書き込みは、Age2chを使って配信されています。
────────────────────────────
Keep your thread alive !
http://pc3.2ch.net/test/read.cgi/software/1041952901/l50
────────────────────────────
つうか、2chとアップローダーは関係無いだろに。
雑談系やニュース系の板はIDもIPも関係ないわな
(^^)
ひろゆきはあほ
氏ね
【予告】小学生の登校を狙って・・・
http://live2.2ch.net/test/read.cgi/news/1042035002/

674 名前:ひろゆき ◆3SHRUNYAXA 投稿日:03/01/08 23:36 ID:1BXnvYvY
通報する人は、IPはあるので管理者に連絡してくれれば、
「捜査関係事項照会書で照会しますよー」って言ってたて伝えてくださいー。

902 名前:ひろゆき ◆3SHRUNYAXA 投稿日:03/01/08 23:41 ID:1BXnvYvY
>警視庁の情報提供っていうフォームで通報していいですか?

フォームでもよいかと。
通報者の電話番号とかもきちんとかいといたほうが
取り上げられる可能性高いです。
ホントは110のほうがいいんですが、、
IP記録スレは有るよ

IP記録実験2
http://news2.2ch.net/test/read.cgi/newsplus/1042030554/
464E:03/01/11 18:23

ある object が 型T のインスタンスだったときに true を返す
Javascript の instanceof みたいなモノを作ってみたんだけど、
イマイチ使用する場面を思い浮かばない。

なんかイイ使い方があったら教えて下さい
>>464
蛇足ですがinstanceof演算子はJScriptですよん。
>>464
それって
 #define instanceof(T, obj) (typeid(obj) == typeid(T))
とか
 template<class T> struct instanceof {
  static bool f( T ) { return true; }
  template<class U> static bool f( U ) { return false; }
 };
とかで十分な気がするんだけど、どんなもんを作ったん?
いまいちよくわからん。

>>465
JavaScript 1.3 以上にはあるよ。ECMAの標準にも入ってるし。
467464:03/01/11 23:10
>>466
あ、そういえば、それでイイじゃん。つーか、そっちの方がいいかも。
俺が作ったのは、こんなモノ

class __object
{
 template< typename Type > struct holder
 {
  static holder* unique()
  {
   static holder obj;
   return obj;
  }
 };
public:
 template< typename InstanceType > __object( InstanceType& ) throw()
  : p_( holder<InstanceType>::unique() )
 {}
 template< typename CompareType > bool instanceof() const throw()
 { return p_ == holder<CompareType>::unique(); }
private:
 void* p_;
};

で、こう使う。
if( __object( obj ).instanceof<T>() ){ ... }
468464:03/01/11 23:23
>>467 にミス。

class __object
{
 template< typename Type > struct holder
 {
  static holder* unique()
  {
   static holder obj;
   // ×return obj;
   return &obj;
  }
  ...

boost::any みたいなものに組み込めば面白いかなとも思ったけど、
type() があるからいらんわなー。
なんか1日無駄に過ごした気分。フゥ
何を今更・・・
ヤツがアニヲタという事がわかるな。
471デフォルトの名無しさん:03/01/12 02:55
どうしても解決できないので教えて下さい。

struct person{
int id;
std::string name;
};

struct personless
{
bool operator()( const person & l, const person & r ) const {
return (l.id < r.id);
}
bool operator()( const person & l, const int & r_id ) const {
return (l.id < r_id);
}
bool operator()( const int & l_id, const person & r ) const {
return (l_id < r.id);
}
};
typedef std::set<person, personless> PersonSet;

このとき
PersonSet ps;
PersonSet::iterator it = ps.find( 5 );

というように、findすると下のようなエラーがでます。
error C2663: 'find' : 2 オーバーロードに 'this' ポインタのための必要な定義がされていません。

これはどうしたら解決できるんでしょうか?
>>471
こんな風にしてもダメ?

struct person {
int id;
std::string name;
person(int i, char* str) : id(i), name(str) {}
};

// 途中略

int main()
{
PersonSet ps;
ps.insert(person(1, "def"));
ps.insert(person(5, "abc"));
PersonSet::iterator it = ps.find(person(5, "abc"));
std::cout << it->id << ' ' << it->name << std::endl;
}
473471:03/01/12 09:17
>472
ええと、IDで検索するのが目的なのでこれではちょっと。
int一つ分冗長になるけれど
std::map<int ,person>
とするしかないのかな。
>>473
VC++(だよね?)付属のSTLをやめて STLport を入れれば解決するらしい。
http://www.google.co.jp/search?q=cache:ucnz7QO5270C:www.dodgson.org/lab/hat/map_like_set.html&hl=ja&ie=UTF-8

でなければ、setの中身オブジェクトの作成コストが低ければ
PersonSet ps;
...
person key = { 5, string("") };
PersonSet::iterator it = ps.find( key );
みたいにダミーのオブジェクトで検索…くらいしかないのではないかなぁ。
 4nd
フォンドボー?
馬鹿が喜ぶだけだからニュースにするなよ
477471:03/01/12 10:32
>>474
そのページ既に見てたのですが一番下のコード、コンパイルとおりますか?
ウチの環境VC6+STLportだと >>471 に示したエラーが出るんです。

って書いてたのですが、Releaseでコンパイルしたら通りました。
デバッグ時にわざわざ
#define_STLP_DEBUG 1
を定義してたのがダメだったようです。コメントアウトしたらデバッグでも
コンパイル通りました。
納得いかないけど解決手段として _STLP_DEBUGを使うのはあきらめます。
>>473
std::setのfindはkeyそのものを探すので、IDで検索したければ、
std::mapのようにkeyとvalueが分離されているコンテナを使った
方がよい。std::setは明らかに不適。
479デフォルトの名無しさん:03/01/12 11:41
Loki::Private::ConversionHelperだけど
MCD本39ページ解説の通りになってるけど
型"U"がコピーコンストラクタをprivateにしてたらコンパイルエラーだよね?

static Small Test(U);
じゃなくて
static Small Test(U&);
にすればいいと思うんだけどダメなのかな?
>>479
それだと二重参照が起きたりしない?
まあちゃんとしたのが使いたければboost/type_traits/is_converson.hpp
を使えってことなんだろうね。Lokiはそもそも教育用のサンプルなんだし。
それにしてもboostのソースはLokiよりも読むのにえらい時間がかかるなあ。
s/converson/convertible/
二重に間違えてスマソ
>>471
std::setのメンバ関数のfindは使えないけど、こんなのはどうだ。

struct person {
int id;
std::string name;
person(int i, char* str) : id(i), name(str) {}
bool operator==(int i) const {
return id == i;
}
};

// 中略

int main()
{
PersonSet ps;
ps.insert(person(1, "def"));
ps.insert(person(5, "abc"));
PersonSet::iterator it = std::find(ps.begin(), ps.end(), 5);
std::cout << it->id << ' ' << it->name << std::endl;
}
あるいは、==演算子をオーバーロードするのが気持ち悪ければ、次のように。

struct person {
int id;
std::string name;
person(int i, char* str) : id(i), name(str) {}
};

class cmp {
int key;
public:
cmp(int i) : key(i) {}
bool operator()(person& p) const {
return key == p.id;
}
};

// 中略

int main()
{
PersonSet ps;
ps.insert(person(1, "def"));
ps.insert(person(5, "abc"));
PersonSet::iterator it = std::find_if(ps.begin(), ps.end(), cmp(5));
std::cout << it->id << ' ' << it->name << std::endl;
}
>>483
それはアホやろ。
>>485
やっぱり?(^_^;)
487デフォルトの名無しさん:03/01/12 19:01
VC6だとunsigned char* から char* に変換できませんとエラーが
でるんだが、VC++.NETだとエラーにならない。...バグなのかなぁ?

#include<sstream>
#include<vector>
using namespace std;
struct a
{
stringstream _Base;
template<typename _Alloc> void operator>>(std::basic_string<unsigned char, std::char_traits<unsigned char>, _Alloc>& str)
{
std::basic_string<char, std::char_traits<char>,_Alloc > strbuf;
( (*this) >> strbuf);//////ここ
str= reinterpret_cast<const unsigned char*>(strbuf.c_str());
}
template<typename _Alloc> void operator>>(std::basic_string<char, std::char_traits<char>, _Alloc>& str)
{
_Base >> str;
}
};

int main()
{
a A;
basic_string<unsigned char> str;
A >> str;
}
>>587
gcc3.2.1だとエラーが多くてコンパイルできない。何とかしてくれ。
489C++厨:03/01/12 19:22
このスレカコイイ!
490デフォルトの名無しさん:03/01/12 19:33
#include<sstream>
#include<vector>
class A
{
public:
std::stringstream _Base;
template<typename _Alloc> void operator>>(std::basic_string<unsigned char, std::char_traits<unsigned char>, _Alloc>& str)
{
std::basic_string<char, std::char_traits<char>,_Alloc > strbuf;
( *this >> strbuf);//////ここ
str.assign(reinterpret_cast<const unsigned char*>(strbuf.c_str()));
}
template<typename _Alloc> void operator>>(std::basic_string<char, std::char_traits<char>, _Alloc>& str)
{
_Base >> str;
}
};

int main()
{
A a;
std::basic_string<unsigned char> str;
a >> str;//(1)NG ->エラー
std::string str2;
a >> str2;//(2)OK
}
491デフォルトの名無しさん:03/01/12 20:11
boostのsmart_ptr全般で、boolへの暗黙の型変換をするとき、
なんでこんなヘンなことやってるの?
operator bool()ではいけないんですか?

// implicit conversion to "bool"
typedef T * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{
 return ptr == 0? 0: &this_type::get;
}
いや、最近のニュー速は本当に良くなってきたと思うよ。
ニュース速報板だからね。
・・・横槍。

削除依頼を内容証明以外の方法で行っても有効ですが、条理が根拠ではありません。
意思表示の一般原則であり自明のことです。
免責の対象にはならないから安心してください。
>>491
smart_ptr p;
int x = p + 1;
こんなクソコード書く奴にコンパイルエラーを叩きつけるため。
495491:03/01/12 20:42
うーん。
http://lists.boost.org/MailArchives/boost/msg38117.php
あたりでやりとりされてるけど、ようわからん。
それによると・・・
・operator bool()ではintへの暗黙の型変換をするからダメ。->なんで?
・private:operator int()してもダメ。->なんで?

gannbattekudasai
497491:03/01/12 20:47
>>494 おっと、入れ違い。
そうか、intになってしまったら*+-/なんかの演算子が許されるのか・・・
今改めてそのスレッド追うの面倒なので記憶に頼って書くけど、
> ・private:operator int()してもダメ。->なんで?
これは結構いいんでない?という結論になったのでなかったか。
 smart_ptr p;
 cout << p << endl;
がコンパイル通ってbool値を表示してしまうという問題はあるけれど。
499デフォルトの名無しさん:03/01/13 01:23
こんな簡単なコードが通りません。

std::basic_string<unsigned char> str;
const unsigned char* p = (const unsigned char*)"abc";
str = p; //もしくはstr.assign(p);

どおして通らないのかどなたかわかりません?
unsignedは何か意味があるの?
>>500
>>487>>490のリストをgccでコンパイルするとエラーになるので、エラーが再現
する最小のプログラムを探していったら>>499になりました。

単にstd::basic_stringをunsigned charで型特定しただけなのになぜエラーが
出るんでしょうね?
bits/basic_string.h見てもよく分からんね。
なにか基本的なことがわかってないっぽい<自分
だから、どんなエラーがでるんだよ。
>>504
リンクエラー
ホゥ、世の中には、「リンクエラー」以上の情報を
報告しようとしない変態リンカが存在するのか、、、
デバッグもさぞ大変な事だな、、
undefined reference to `std::char_traits<unsigned char>::length(unsigned char const*)'
undefined reference to `std::char_traits<unsigned char>::copy(unsigned char*, unsigned char const*, unsigned)'
undefined reference to `std::char_traits<unsigned char>::move(unsigned char*, unsigned char const*, unsigned)'
undefined reference to `std::char_traits<unsigned char>::copy(unsigned char*, unsigned char const*, unsigned)'
undefined reference to `std::char_traits<unsigned char>::copy(unsigned char*, unsigned char const*, unsigned)'
undefined reference to `std::char_traits<unsigned char>::move(unsigned char*, unsigned char const*, unsigned)'
undefined reference to `std::char_traits<unsigned char>::copy(unsigned char*, unsigned char const*, unsigned)'
です
$ g++ -v
gcc version 2.95.2 19991024 (release)
では、ちゃんとコンパイル・リンクできたが。
>>506
書いてあるとおりだと思うが。std::char_traits<>::xxx() ってテンプレート
関数を unsigned char で特殊化したものを用意しろ、ってことだろ。
これってgcc3.xのbits/char_traits.hバグ?
それともSTLの仕様?
バグならバグレポート書きたいのだけど。
> バグならバグレポート書きたいのだけど。
そのレベルの人間は、規格書をチェックでしょう。
http://www.cuj.com/experts/1911/reeves.htm?topic=experts
ここを見る限りじゃどうもバグじゃないっぽい。
bits/char_traits.hの中を見れば<char>と<wchar_t>しか処理が書かれて
なくて、それ以外の型を処理の書かれてないデフォルトで
拾うようになっている。ということはunsigned char、signed charは
使うなっていう暗黙のメッセージなのかな、これは?

http://www.bohyoh.com/CandCPP/FAQ/FAQ00001.html
ただここに書かれているように"char"の符号の有無は処理系依存なんだよねえ。
この辺はどうするつもりなんだろう。gcc以外のコンパイラなど使うなっていう意味かな??w
>>508-511
499です。
charとwcahr_tで型特定されているのは、多分効率を重視するためでしょうね。
その反面、basic_stringで独自の型を用意しようとすると、assign()などのメンバ
を自分で用意してやらないといけなくなったと。

これで、悩まずに済むようになりました。ありがとうございました。
Borland-C++5.6.2では、basic_stringにunsigned charを指定してもエラー
にはなりません。それは、多分型特定してないからですね。
Include\stl\string.hを見てもそれらしい型特定はありません。

Borland-C++5.6.2はSTLportなので、確実な事は言えませんがgccでも
STLportを導入すればunsigned charの問題は回避できるような気がします。
514山崎渉:03/01/13 18:26
(^^)
こんなアホサイトに人生振り回される奴もどうかしてるがな
516質問:03/01/15 12:45
こういうのって loki にはないですか?

template<int v> struct Int2Type{
public: enum { Value = v };
};

template<typename T1, typename T2, bool isT1GreaterThanT2> struct SizeCompareRaw {
typedef int Greater;
typedef int Lesser;
};

template<typename T1, typename T2> struct SizeCompareRaw<T1, T2, true> {
typedef T1 Greater;
typedef T2 Lesser;
};
template<typename T1, typename T2> struct SizeCompareRaw<T1, T2, false> {
typedef T2 Greater;
typedef T1 Lesser;
};

template<typename T1, typename T2> struct SizeCompare{
typedef SizeCompareRaw<T1, T2, Int2Type<(sizeof(T1) > sizeof(T2))>::Value >::Greater Greater;
typedef SizeCompareRaw<T1, T2, Int2Type<(sizeof(T1) > sizeof(T2))>::Value >::Lesser Lesser;
};

typedef SizeCompare<SizeCompare<int, char>::Greater, long long>::Greater GreatestType;

もしあったら、もっと単純できれいな実装でしょうか?
>>516
何がしたいのか、日本語で書いてみないか?
>>516
> loki にはないですか?
Loki は小さいから自分で調べてみるとよろし。
少なくとも俺の記憶では、そのものズバリは無いんじゃないかと…

> もっと単純
Int2Type 使わなくともいいと思う。
あと、1番上の SizeCompareRaw の定義はいらない。

Loki::Select を再利用するとか…
template<class T, class U> Large {
  typedef Select<sizeof(T) > sizeof(U), T, U>::Result Result;
};
519山崎渉:03/01/15 17:52
(^^)
520デフォルトの名無しさん:03/01/15 18:34
式templateとかで静的な値を得るのに
特別な技法を使うんじゃなく、
構文が使えたら便利だよね。
(回りくどい表現になりがちだから。)
521516:03/01/16 01:41
みなさんレスありがとうございます。
>>517
サイズの大きい方の型を得たかったのです。

>>518
上のソースが、Modern C++ を読んでから自分ではじめて考えた
generative 風のコードなので
(モダ++に)解説されている範囲外は、ソース見ても、まださっぱりなんですよ^^;
(見ても求めているものかどうかよくわからないんです、試せばいいのですが…^^; 本格的に g++ に乗り換えかな…)
これから少しずつ精進していこうと思います。
Int2Type を使わないで書くとどういう感じなのでしょう?
さっぱり思い当たらないのですが、ヒントだけでもいただけないでしょうか?

>>520
host-policy とかも、文法レベルでサポートしてほしいですよね。
loki を見てると、ライブラリでやる範疇をそろそろ超えているような気が…
(いい意味で捕らえると C++ の(これまでの)限界を打ち破る力だと思うのですが…)
>>521
Lokiが使えるなら、ヒントどころか答えが>>518に書いてあると思うんだが。
523デフォルトの名無しさん:03/01/16 12:47
教えてください。

tupleのvectorをtupleの第1要素でソートしたいときどうしたらいいんでしょう。

typedef boost::tuple<int, double> Tuple;

std::vector<Tuple> data;
// data.push_back(boost::make_tuple(1, 1.0)); ....

std::sort(data.begin(), data.end(),
boost::bind(
std::less<int>(),
boost::bind(boost::mem_fn(&Tuple::get<0>, _1),
boost::bind(boost::mem_fn(&Tuple::get<0>, _2)
));

これだとコンパイル通りませんでした。
(BCB6で「コンパイラ内部のエラー」)

なんか間違ってるでしょうか。
それか、こういう場合もっと簡単な方法があるんでしょうか?
何気に難しいな、どうやるんだろ
力ずくで良いなら

struct CompByTuple1st
{
  bool operator()(const Tuple& t1, const Tuple& t2)
  {
    return t1.get_head() < t2.get_head();
  }
};

を比較用の関数オブジェクトとして sort に渡す、かねぇ。汎用性ゼロ
だが。
>>523
それであってる (gccなら通る) 。…が、その場合 mem_fn はなくてもOK。
BCBでまともに boost::bind を動かすのはあきらめた方が無難ではないかと。
527デフォルトの名無しさん:03/01/17 10:33
皆さんありがとうございました。BCBでbind系が使えるようになる日を待ちます。
とりあえず、比較オブジェクトをtemplateにして

template <typename T, int I>
struct CompareByNth
{
bool operator()(const T & a, const T & b) const
{
return a.get<I>() < b.get<I>();
}
};

で逃げることにしました。これにstd::lessを簡単に渡せればいいんですけど…
>>526
gccで通った?俺はg++3.2.1で試してみたが、
C:/MinGW/Learn/boost/tuple.cpp:18: no matching function for call to `mem_fn(
<unknown type>, boost::arg<1>&)'

C:/MinGW/Learn/boost/tuple.cpp:19: no matching function for call to `mem_fn(
<unknown type>, boost::arg<2>&)'
C:/MinGW/Learn/boost/tuple.cpp:21: parse error before `;' token
なんてエラーが出やがる。
g++も駄目か
>>528>>529
boost::mem_fnを取ったらg++で通ったよ。
531526:03/01/18 01:21
>>528
あーほんとだ。523のをコピペじゃなくて書き写したんで、微妙に
違うコードをコンパイルしてたわ。
sort( data.begin(), data.end(),
 bind( less<int>(),
  bind( mem_fn(&Tuple::get<0>), _1),
  bind( mem_fn(&Tuple::get<0>), _2) ));
//mem_fnは無くてOK。
532デフォルトの名無しさん:03/01/19 15:53
std::accumulateを使ってプログラムを書いてみたのですが、何かこうもっと
スマートに書けないものでしょうか?

struct A {
virtual int func() {
return 1;
}
};

struct B : public A {
int func() {
return 2;
}
};

int AddA(int i, A* a)
{
return i + a->func();
}
533デフォルトの名無しさん:03/01/19 15:53
int main()
{
std::vector<A*> a;
const int maxi = 100000;

for (int i = 0; i < maxi; i++)
if (std::rand() % 2)
a.push_back(new A);
else
a.push_back(new B);

int i;
std::accumulate(a.begin(), a.end(), 0, AddA);
std::cout << i << std::endl;
}
>>533
back_inserter と generator 使うと、もっとうまく書けそうな予感。
うーんこれでもまだ不格好だ・・・・

struct Add {
int value;
Add(int i) : value(i) {}
void operator()(A* a) {
value += a->func();
}
};

int main()
{
std::vector<A*> a;
const int maxi = 100000;

for (int i = 0; i < maxi; i++)
if (std::rand() % 2)
a.push_back(new A);
else
a.push_back(new B);

int i;
i = std::for_each(a.begin(), a.end(), Add(0)).value;
std::cout << i << std::endl;
}
>>534
back_inserterを使うという事は、他のvectorに値を入れるという事でしょうか?
できました。もう一個vectorを使ってやってみました。こんな感じでしょうか?

int main()
{
std::vector<A*> a;
std::vector<int> b;
const int maxi = 100000;

for (int i = 0; i < maxi; i++)
if (std::rand() % 2)
a.push_back(new A);
else
a.push_back(new B);

std::transform(a.begin(), a.end(), std::back_inserter(b), std::mem_fun(&A::func));

int i;
i = std::accumulate(b.begin(), b.end(), 0);
std::cout << i << std::endl;
}
さらにアルゴリズムを使ってみました。私にはこの辺が限界です。

inline A* gen()
{
return (std::rand() % 2) ? new A : new B;
}

int main()
{
std::vector<A*> a;
std::vector<int> b;
const int maxi = 100000;

std:generate_n(std::back_inserter(a), maxi, gen);
std::transform(a.begin(), a.end(), std::back_inserter(b), std::mem_fun(&A::func));

int i;
i = std::accumulate(b.begin(), b.end(), 0);
std::cout << i << std::endl;
}
もう一個vectorなんて、許さん。

#include <boost/iterator_adaptors.hpp>
int accumulate( const std::vector< A* >& v )
{
    std::mem_fun_t< int , A > func( &A::func );
    return std::accumulate(   boost::make_transform_iterator( v.begin() , func )
                            , boost::make_transform_iterator( v.end() , func )
                            , 0 );
}
gcc2.95を使ってるんだけど、ちょっと複雑なテンプレートで
すぐにInternal compiler errorを吐きやがります。
VC6は食います。

そんなもんですかね。
>>539
すげー!こんなコードが書けるのか。
やっぱりSTLやboostは奥が深いですねえ。
>>540
VCも使ってるって事は、gccはcygwinかMinGW?
>>542
YES YES YES
gcc3,VC7ではもちろんとおります
>>543
gcc2.95.2にこだわる理由は何?
もしかして仕事で使っているとか?
>>538
std::vector<A*> a を generate_n で作るまでは OK として、その後は

  std::accumulate(v.begin(), v.end(), 0,
        boost::compose_f_gx_hy(
          std::plus<int>(),
          std::identity<int>(),
          std::mem_fun(&A::func)
        ));

ってな感じでどう?
546545:03/01/19 17:33
>>539
うまいな。そっちの方が見やすいかもしれん。

>>540
template 使いたいなら gcc 3 系列に移行しましょう。

…俺も仕事でいまだに gcc 2.96 使ってるけど、早く捨てたい。
547543:03/01/19 17:41
趣味だったらVC7/GCC3にするって。
仕事なんでVC6/GCC2.95を使わざるをえません。

あれからいろいろいじったけど、
どうやってもgcc2.95で通らないんだな。

vc6は、使うものしか処理しないって感じだねえ。
gcc2.95は、使おうが使うまいが、ある程度処理するみたい。
落ちてるところは実際には使われない部分だったりするからナントモ。
>>545
std::identityってのは初めて見ました。ここの文脈ではint()とは書けないから
必要なんですね。標準C++には無いようですが、STLportには幸いにも装備
されていました。
ところでg++3.2.1でstd::identityがエラーが出るのですが、boostには
これの代用になる物がありますか?
>>549
簡単なものだから、自分で書いちゃっても。
これは要するに

 f(x) = x

となるような恒等変換をする関数オブジェクト。

namespace std {
  template <typename T>
  struct identity : public unary_function<T, T>
  {
    T& operator()(T& x) const { return x; }
    const T& operator()(const T& x) const { return x; }
  };
}
>>550
なるほど、関数オブジェクト化すればよかったのですね。
ありがとうございます。
552デフォルトの名無しさん:03/01/19 18:51
template<bool Val>
struct A{
   template<class T> struct B{};
};
template<class T1,class T2>
struct C{
   typedef A<sizeof(T1)==sizeof(T2)>::B<T1> type;
};
main(){
   A<sizeof(int)==sizeof(int)>::B<int> val1; // ここはエラーにならない
   C<int,int>::type val2; // ここでエラー
}
これって文法的にはどうなんでしょうか?

VC7とDigital Mars C++では通るのですが、
去年の夏ごろのmingwではコンパイラ内部エラーになり、
冬に出たmingwでは内部エラーにはならないもののコンパイルできないのです。
vectorクラスにpush_backしたらポインタがふっとんでがびーん
554543:03/01/19 23:20
ようやく最小限のコードになったよ・・・

-----
// gcc2.95(cygwin)でinternal compiler error

template<typename T>
struct A {
  T* pT;
};

//template<typename V>
struct B {
  template<typename T>
  struct C : public A<T> {
    void func(T* pT) {
      return;
    }
  };
};
-----

中央のコメントアウトしたのを外すと通し、使える。
ひょっとして外出?
>>554
手元の処理系で試してみたけど

× gcc version 2.95.4 20020320 [FreeBSD]
○ gcc version 2.96-ee-001003-1
○ gcc version 3.2 (mingw special 20020817-1)

ってことで gcc 2.96 で修正済みのバグと思われ。
>>555
検証サンクス。gcc2.95そのもののバグなのね。
とりあえずB<void>でworkaroundしときます。

これでようやくVC6と合わせられる・・・
557デフォルトの名無しさん:03/01/20 16:08
stlのmapコンテナで
map<string,int> WD;
としている時に
mapのsecondの値(int)の大小を比較して大きい順にソートするよい方法って
ないですか?
最終的にはそのソートされたfirst(string)を順番に表示したいのですが。
>>557
firstとsecondを逆にして他のmapに挿入し直す。
559デフォルトの名無しさん:03/01/20 16:24
>>557
ありがとうございます。
intをキー値に持つマップに格納してみます。
STLportのstd::mapとstd::hash_mapの速度がどれくらい違うか実験してみました。
コンパイラはBorland-C++5.6.2です。

hash_map insert(10) = 107
map insert (10) = 114
hash_map lookup(10) = 48
map lookup (10) = 29
hash_map insert(100) = 486
map insert (100) = 708
hash_map lookup(100) = 289
map lookup (100) = 277
hash_map insert(1000) = 5395
map insert (1000) = 7743
hash_map lookup(1000) = 2593
map lookup (1000) = 3586
hash_map insert(10000) = 54202
map insert (10000) = 93014
hash_map lookup(10000) = 28221
map lookup (10000) = 54862
hash_map insert(100000) = 839600
map insert (100000) = 1476372
hash_map lookup(100000) = 335070
map lookup (100000) = 1084240
hash_map insert(500000) = 3934177
map insert (500000) = 9722710
hash_map lookup(500000) = 1835211
map lookup (500000) = 7610511

予想以上の差に驚いています。要素の数が増大すればする程差が開いて
行きますね。
561デフォルトの名無しさん:03/01/20 22:11
boost::function1<bool,int,int> とか boost::function1<int,int,int> とかを
まとめてvectorとかに入れたいんだけど、どうすればいいかな?
562デフォルトの名無しさん:03/01/20 22:13
  ∋8ノノハ.∩
   川o・-・)ノ <先生!こんなのがありました!
__/ /    /   
\(_ノ ̄ ̄ ̄\
||ヽ|| ̄ ̄ ̄ ̄||
 ...|| ̄ ̄ ̄ ̄||
http://saitama.gasuki.com/hiroyuki/
563デフォルトの名無しさん:03/01/21 10:35
>>562
金融のバナーばっかり
564557:03/01/21 11:44
>>558さんの言うとおりに<string, int>の新しいマップ関数を定義して
firstとsecondを入れ替えてみたのですがこれを出力すると
intの数値が同じものはstring部がすべて表示できませんでした。
このように数値が重複しているものでも別々に出力するにはどうすれば
いいのでしょうか?
>>564
multimap
>564
そのくらいは自分で分かるようになりなよ…。
そもそも連想配列が分かってないんじゃ?
>>564

int main()
{
std::map<std::string, int> si;

si["abc"] = 1;
si["def"] = 1;
si["ghi"] = 2;

std::multimap<int, std::string> is;
std::map<std::string, int>::iterator sii;

for (sii = si.begin(); sii != si.end(); ++sii)
is.insert(std::make_pair(sii->second, sii->first));

std::multimap<int, std::string>::iterator isi;
for (isi = is.begin(); isi != is.end(); ++isi)
std::cout << isi->first << ' ' << isi->second << std::endl;
}
568デフォルトの名無しさん:03/01/23 00:03
gcc (GCC) 3.2 20020927 (prerelease) on Cygwin(1.3.18-1)でコンパイル通らないんですけど何故に?
ちなみに1次元配列なら全然問題ないんスけど。教えてぷりーず。

#include <vector>
using namespace std;
int main()
{
vector<vector<int> > IntAry;
IntAry.assign(5);// 5 x 6 array
for(int i=0; i<IntAry.size(); i++) IntAry[i].assign(6);
}
>>568
コンパイルエラーを省くなとあれほど・・・・
>>568
vector.assign(int)というメンバ関数はないっス・・・・・・
>>568
この場合はresize()では。
>>568
vector<vector<int> > IntAry(5, vector<int>(6, 0));
573デフォルトの名無しさん:03/01/23 05:28
getch( )の( )って何のタメにあるの?
中に何か入るの?
>>537
受け取るための袋だろ?
おまいら、アホみたいに頭いいな。感動した。
>>573
関数のプロトタイプないし呼び出しにて、「引数が何も無い」 事を示している。
括弧をつけないと、関数のプロトタイプないし呼び出しではなく関数へのポインタを得る事になる。
577山崎渉:03/01/23 20:00
(^^)
>>570
スマソ。投稿後すぐに分かった。
>>572
何故分かるの?凄すぎ。出直し逝ってきます。
>>578
std::vectorには、vector c(n, elem) というコンストラクタがある。
elemの要素をn個コピーして初期化する。
って書かなくてもわかるよね。
いい加減にboostをSTLに組み込めと。
いい加減にboostをSTLに組み込めと。
いい加減にboostにSTLを組み込めと。
>>580-582
標準C++の次期規格が固まる時まで無理だと思ふ。
あっboost「に」STL「を」組み込むのか。なぜそんな事をする必要があるの?
そうなったらstdのコンテナは使わないって意味?
>>584
>>582は完全にネタだろ。
Loki::SmartPtrのOwnershipパラメータ用Lokiが定義してるポリシーのうち、
Loki::RefCountedMTだけテンプレートパラメータの数が違う気がするんですが、
これでいいんですか?
gccだとコンパイル通りませんが。

int main(void){
  Loki::SmartPtr<int, Loki::RefCountedMT> p;
  return 0;
}

過去ログ一応見ましたが、がいしゅつだったらご免なさい。
587デフォルトの名無しさん:03/01/26 00:05
今、boost の weak_ptr のソースを読んでいて、
(文法レベルで)ちょっとわからない事があったのですが、
コンストラクタの引数の

template<typename Y>
weak_ptr(weak_ptr<Y> const & r)

という書き方、これは一体何を表しているのでしょうか?
生のポインタなら Y* const はわかるのですが、それって対応するのは
weak_ptr<const Y> ですよね?
ポインタ自体が const なら const weak_ptr<Y> ですよね?
weak_ptr<Y> const& っていうのは何を表しているんでしょうか?
>>587
const AAA &

AAA const &
は同じ意味。
589587:03/01/26 00:12
>>588
ななななんと!知りませんでした…。そんな書き方ができるとは…。
ありがとうございました。読みづらい…鬱だ…。
591587:03/01/26 00:50
質問続きでスミマセン。

VC++6.0 で boost::mem_fn を自作スマートポインタに適用しようとしたら

C:\Program Files\Microsoft Visual Studio\VC98\include\xmemory(34) : error C2660: 'new' : 関数が不正な 2 個の実引数をともなって呼び出されました。
C:\Program Files\Microsoft Visual Studio\VC98\include\xmemory(66) : コンパイルされたクラスのテンプレートのインスタンス化 'void __cdecl std::_Construct(MyPtr<PointeeType> *,const MyPtr<PointeeType> &)' の参照を確認してください

みたいなエラーになりました。何がいけないか以上の情報でわかる人いますか?
ちなみに同じ状況で自作スマートポインタを boost::shared_ptr に変えると
コンパイル通るのです。

>>590
激しく鬱ですね…。ポインタが全て Ptr<PointeeType> みたいな書式になって
配列を int[] num; みたいに書ければ const が全て直後の型に掛かる。で統一できるのに…。
>>591
boost::mem_fn 側ではnewもstd::allocatorも一つも使っていないようだが…。
そのエラーは他の場所が原因に見える。あと、mem_fn を使うには
namespace boost {
  template<typename T> T* get_pointer( const T& p ) { return &*p; }
}
が必要だが、書いてる?

>>589
boost coding guildline。らしい。
http://groups.yahoo.com/group/boost/files/coding_guidelines.html#decl_initialization
593デフォルトの名無しさん:03/01/26 10:52
VisualStdio6.0を使っていますがexportが使えないようなのですがそれに代わるものは何かあるのでしょうか?
export が使える処理系って、comeau くらい? って、使ったことないけど。
で、プログラム内でのそのテンプレートの使い方が限られているなら
明示的インスタンス生成ですな。
>>592
そのガイドラインの評価ってどうなってんの?
596デフォルトの名無しさん:03/01/26 13:12
重複チェックをする場合としない場合の両方に対応する必要があるプログラムを作成しています。
そこでSTLのsetとmultisetを使おうと思って以下のように書いたんですが、
ソースのいたるところでif(cyofukuOK)の分岐だらけになってしまってます。
もっといい方法ないでしょうか?


set<AnsiString> setContainer
multiset<AnsiString> multiContainer
//以下略


if(cyofukuOK)
multiContainer.insert(tmp);
else
setContainer.insert(tmp);
>>596
multisetを操作するラッパーを作ればいいんじゃねーの?
>>596
std::set, std::multiset を直にコードに埋めずに、

1) std::set を保持し、それを操作するクラス。
2) std::multiset を保持し、それを操作するクラス。

と二つに分けてしまう。

Set* pSet;
if (cyofukuOK)
  pMap = new MultiSet();
else
  pMap = new UniqueSet();

struct Set {
  virtual void insert(AnsiString) = 0;
  ...
};

class UniqueSet : public Set {
  std::set<AnsiString> container_;
public:
  void insert(AnsiString s) { container_.insert(s); }
};

class MultiSet : public Set {
  std::set<AnsiString> container_;
public:
  void insert(AnsiString s) { container_.insert(s); }
};
599デフォルトの名無しさん:03/01/26 14:31
596です。
598さん、ありがとうございます。
早速やってみました。
コンテナに保持するまではうまくいったのですが、
iteratorはどうやって保持すればいいんでしょうか?
以下のようにすると特化パラメータを指定しろというエラーメッセージが出るのですが、よくわかりません。
forで使うのでbegin(),end()も必要なんでしょうかね?やはり・・

struct mySet {
virtual void insert(AnsiString) = 0;
virtual iterator getiterator(void) = 0;
};
class UniqueSet : public mySet {
std::set<AnsiString> container_;
std::set<AnsiString>::iterator itrator_;
public:
void insert(AnsiString s) { container_.insert(s); }
iterator getiterator(void) { return itrator_; }
};

class MultiSet : public mySet {
std::multiset<AnsiString> container_;
std::multiset<AnsiString>::iterator itrator_;
public:
void insert(AnsiString s) { container_.insert(s); }
iterator getiterator(void) { return itrator_; }
};
600デフォルトの名無しさん:03/01/26 14:32
596です。
ちなみに現状はこんな感じです。
typedef set<AnsiString> SetContainer;
typedef SetContainer::iterator SetIterator;
SetContainer Container
;
if (cyofukuOK)
{
for(SetIterator it=Container.begin();it!=Container.end();++it)
TRichEdit1->Lines->Add(*it);
{
else
{
以下略
}
601591:03/01/26 14:58
おはよう(?)ございます。

>>592
か、書いてませんでした。下記のような感じのオーバーロードでいいのでしょうか?
namespace boost
{
 template <typename T>
 T* get_pointer(const MyNamespace::MyPtr<T>& smartPtr)
 {
  return &(*smartPtr);
 }
}

ちなみにこれを書いてもエラーメッセージは何も変わりませんでした。
よろしくお願いします。
>>599
> 以下のようにすると特化パラメータを指定しろというエラーメッセージが出るのですが、
そりゃ

> iterator getiterator(void) { return itrator_; }
ここの戻り値の型である iterator ってのが、テンプレート型だからでしょ。クラス定義
の中に

typedef std::set<AnsiString>::iterator iterator;

とでも追加しとかんと。
603デフォルトの名無しさん:03/01/26 15:11
ちょっと質問。
vector<T> vec; が格納している要素列の先頭アドレスを得るのに
&vec[0] とやると思うんだけど、この操作は、vec.empty() == true
の時も有効でしょうか。
>>603 だめだろ。
>>604
&vec[0] に「書き込む」のはダメだが、&vec[0] を取得するのは問題ないと思うぞ。
>>602
あなたひどいひとね。
>>605
その式の値をどう使うつもりだ?
608605:03/01/26 15:32
ごめん、やっぱりダメかも。operator[] ではなく at 使うと例外投げるのが仕様だし。
>>607
イテレータ同士の比較とか、C 関数に渡す場合には使えるよね。

/* 要素数 num の int 配列を処理する */
extern "C" void foo(int *data, size_t num);

vector<int> v;
..
foo(&vec[0], vec.size());
610デフォルトの名無しさん:03/01/26 15:55
596です
解決しました。
思いっきり勘違いしてました。最終的に以下のようになりました。
ありがとうございました。
//.h
struct mySet {
virtual void insert(AnsiString&) = 0;
virtual unsigned int getSize(void) = 0;
typedef std::set<AnsiString>::iterator iterator;
virtual iterator begin(void) = 0;
virtual iterator end(void) = 0;
};
//.cpp
auto_ptr<mySet> pSet;
if(RepeatDataCheckBox->Checked)//重複なし
{
auto_ptr<UniqueSet> instance (new UniqueSet());
pSet = instance;
}
else //重複あり
{
auto_ptr<MultiSet> instance (new MultiSet());
pSet = instance;
}
pSet->insert(tmp);
typedef std::set<AnsiString>::iterator iterator;
for(iterator it = pSet->begin();it!=pSet->end();++it)
{
ed->Lines->Add(*it);
}
v[n]は*(v.begin()+n)と定義されていて(23.1.1 -12-)、
v.empty()のとき、v.begin()は"past-the-end"っていう値を返すことになってる(23.1 -7-)。
イテレーターiについて、*iが定義されるようなiの値を、"dereferencable"っていう
けど、"past-the-end"は"dereferencable"じゃぁない(24.1 -5-)。

ってことで、v.empty()のとき、v[0]は
"dereferencable"ではないイテレーターに operator * を適用することになるので、
未定義である。

あとから & つけたところで手遅れだと思われ。
612605:03/01/26 16:05
仕様書調べてみたよ。

コンテナ a の operator[](int n) は *(a.begin() + n) と定義されているから、n = 0 のときに
*a.begin() (== *a.end()) が許されるか否かが問題。

a.end() は常に past-the-end-value (有効な要素の『次』を指す) イテレータを返し、これ


> 24.1 Iterator requirements
> 6. (前略) Values of an iterator i for which the expression *i is defined are called
> dereferenceable. The library never assumes that past-the-end values are
> dereferenceable

ということでデリファレンスしてはいけない。つまり *a.begin() という表記は NG で、
従って &a[0] も NG ってことになる。

ただし、現実には参照はコンパイラ内部ではポインタとして実装されてるから

vector<int> v;
int& n = &v[0];
int* p = &n;

とした場合でも p (n のアドレス) だけ見てる分には問題ない。ただし *p = 1 とか
int x = *p といったように、n の値を読み書きすると、一般保護違反で落ちたりメモリ
壊したりする。

……ってことかね。
613605:03/01/26 16:05
一足遅かったか…
>>610
その場合、mySetのデストラクタにvirtualが要る。

MultiSetの実装が謎だ。なんでコンパイルとおるんだ?
絶対解決してないと思うんだが?
>>611
vector<T>::iterator が T* という良くある環境だと問題ないけど、STLport の
デバッグモードみたいに別の型が返ってくる(それをデリファレンスすると T
になる)だと、怒られそうな気がする。

とはいえ微妙に使いにくい仕様だな、これ。>>609 にあるような C 言語の関
数を呼ぶ場合、どうせ C 関数の方で要素数チェックして 0 なら何もしない、
ってのが普通だし、そっちにチェックを任せたいよな。
616611:03/01/26 16:11
ニヤリ
617デフォルトの名無しさん:03/01/26 16:12
610です
このようにしましたけど、問題ないようです。
環境はBCB5でWindowsXPです。

//重複なしのコンテナ
class UniqueSet : public mySet {
std::set<AnsiString> container_;
std::set<AnsiString>::iterator itrator_;
public:
void insert(AnsiString& s) { container_.insert(s); }
unsigned int getSize(void){ return container_.size(); }
iterator begin(void){ return container_.begin(); }
iterator end(void){ return container_.end(); }
};
//重複ありのコンテナ
class MultiSet : public mySet {
std::multiset<AnsiString> container_;
std::multiset<AnsiString>::iterator itrator_;
public:
void insert(AnsiString& s) { container_.insert(s); }
unsigned int getSize(void){ return container_.size(); }
iterator begin(void){ return container_.begin(); }
iterator end(void){ return container_.end(); }
};
std::set<int>::iterator f() { return std::multiset<int>::iterator(); }

gccでも↑のコードがエラーにならん。
仕様じゃ、ないよな?
>>615
size()==0よりもempty()を使えって話になるんじゃないか?
>>619
それでも

extern "C" void foo(int *data, size_t num);

に対して、これを利用する C++ 側関数は

vector<int> v;
if (!v.empty())
  foo(&v[0], v.size());

と場合分けが必要になるよね。
>>620
↓で問題ないと思う。

inline
void foo( vector<int>& v )
{
  if(!v.empty())
    foo(&v[0],v.size());
}
>>621
俺だったらこんな関数作って使うかな。

templat<class T>
inline T* GetFirstPointer( vector<T>& v )
{
 if(v.empty())
  return NULL;
 else
  return &v[0];
}

で、vectorが空でも&v[0]が許される実装で、
かつ効率が気になる場合は
単純に&v[0]を返すように書き換えると。
623622:03/01/26 17:37

誤:templat<class T>
正:template<class T>
>>622
>621のコードを見てなお、>622のコードを使いたくなるのって、どんなとき?
悲しいときー
>>624
ラッパ関数を沢山書くのが面倒な場合だろう。
627622:03/01/26 18:35
>>624
fooに相当する関数が沢山あるとき。
628622:03/01/26 18:54
カブった....。

あとfooが関数オブジェクトだった時や、
fooがvectorのサイズを変更しないことを示したい時にも
>622の方を使いたくなるな。
>>627
ということは、末端のコードにGetFirstPointerがばら撒かれるわけか。
  foo(GetFirstPointer(v),v.size());
・・・うーん、あんまり賛成できないなぁ。
630629:03/01/26 19:02
>>628
> fooがvectorのサイズを変更しないことを示したい時にも

あー、それあるなぁ。
やっぱりしょうがないかぁ。
>>629
いっそ vector 継承して operator[] だけ再定義したオブジェクトを作るのも
手かもしれんな。

メンバ変数は一切増えないから、デストラクタが virtual でなくとも支障ない
しさ。
632629:03/01/26 19:43
>>631
そりゃあんまりだ。
>>611-612
でもさ、vector::operator[] って reference を返すじゃん。
てことは、&v[0] は dereference を実行してないと思うんだけど。

まあでも、v.size() == 0 の場合、要素配列を格納するための
有効なバッファがが確保されているかどうかは不明だしねぇ。
やっぱり v.empty() で切り分けるしかないかなぁ。
>>633
> でもさ、vector::operator[] って reference を返すじゃん。
で、規格書読むと reference は「有効なオブジェクトを指さねばならない」と書いてあったり
するわけだ。

> てことは、&v[0] は dereference を実行してないと思うんだけど。
これは &(*v.begin()) と同じ意味なんだが、v.begin() が返すのが単なるポインタではない
場合には、実際に dereference が行われた上で、そのアドレスが計算されることになる。
たいていの処理系だと vector<T>::iterator は T* だから問題ないけど。
635601:03/01/26 21:58
>>592
やはり別の理由でした。自作スマートポインタが、変な形式の operator new を持っていたのがいけなかったようです。
(g++ に切り替えてわかったのですが、boost::mem_fn ではなくて、その前のコンテナに突っ込むところでのエラーだったようです。)
それを取り除いて、自作ポインタ用の get_pointer を追加した所、うまくいきました。

ありがとうございました。
636635:03/01/26 22:34
それと気がついた事を一つ。

get_pointer は koenig look-up があるので 名前空間 boost に入れなくても
よさそうです。
637592:03/01/26 23:34
>>636
VC6って演算子じゃない関数は Koenig Lookup 出来ないんじゃなかったっけ。
最近使ってないからはっきり覚えてはいないけど…。
昔、数値計算用に3次元や2次元ベクトルクラス(double型のみ)を自作したりしたんだけど、
最近になってテンプレート化してみたら、同じ型同士は問題なく動くけど
違う型を混ぜると下のように怒られちゃいました。
型をあわせなきゃいけないみたいだけどどうすればいいのでしょう……


borland c++ 5.5でつ

vec3<double> a
vec3< complex<double> > b,c

c=a*b;

『エラー E2094 : * 演算子が使われたがクラス Vec3<complex<double >> では Vec3<double> 型のための定義が存在しない』
vec3<double> + vec3< complex<double> > で、あなたの書いたどのコードが
実行されると期待しているんだ?
>>638
本質的には T から U への型変換が存在する時に、vec<T> から vec<U> への
型変換を認めたい、って話だよね。

それなら、テンプレート化したコピーコンストラクタを作る。vec3 の実装がどうなっ
てるか知らんけど、かりに vec3<T> が private 変数として T 型の配列 v_[3] を
持つと仮定すると、

template <typename T>
class vec3
{
public:
  template <typeename U>
  vec3(const vec3<U>& other)
    : v_(other.v_)
  {}
};

ってな感じ。other.v_ (U[3]型) から v_ (T[3] 型) への暗黙の型変換がある場合、
これでよろしく変換できる。
ありがとう。何を調べればよいのかが解らないと自分一人ではどうにもならんので。

配列だと余分なアクセス入るかなと思って、ベクトルの各成分はT v[3]じゃなくてT x,y,zで実装してます。
もっと次数が高ければ当然配列にするだろうけど……あ、配列だったらSTLのvector使えばいいのか。

明日試してみます
テンプレートクラスをstd::ostreamに出力するにはどのように定義すれば
いいのでしょうか?
コンパイルできるのですがワーニングが出ます。gcc3.2.1(MinGW)です。

template <typename T>
class A {
T value;
public:
A(double d = 0) {
value = d;
}
friend std::ostream& operator<<(std::ostream& os, const A<T>& a);
};

std::ostream& operator<<(std::ostream& os, const A<double>& a)
{
os << a.value;
return os;
}

int main()
{
A<double> a(1.23);
std::cout << a << std::endl;
}
>>642
なんでそのコンパイラの出力をはぶきやがるんだ?
>>643
すみません、ワーニングをコピペします。

g++.exe "C:\MinGW\Learn\Learn2\template_ostream.cpp" -o "C:\MinGW\Learn\Learn2\template_ostream.exe" -Wall -s -O3 -I"C:\mingw\include" -I"C:\mingw\include\c++" -I"C:\mingw\include" -L"C:\mingw\lib"
C:/MinGW/Learn/Learn2/template_ostream.cpp:10: warning: friend declaration `
std::ostream& operator<<(std::ostream&, const A<T>&)' declares a
non-template function
C:/MinGW/Learn/Learn2/template_ostream.cpp:10: warning: (if this is not what
you intended, make sure the function template has already been declared and
add <> after the function name here) -Wno-non-template-friend disables this
warning

Execution terminated
Compilation successful
>>644
Friend declaration `std::ostream& operator<<(std::ostream&, const A<T>&)'
declares a non-template function.
If this is not what you intended, make sure the function template has
already been declared and add <> after the function name here.
-Wno-non-template-friend disables this warning.

・・・ってなワケだ。あとは好きなように対処しな。
>>645
次のようにしたらコンパイル通りました。ありがとうございました。
ちなみにBCC5.6では通りませんね。

template <typename T>
class A {
T value;
public:
A(double d = 0) {
value = d;
}
friend std::ostream& operator<< <>(std::ostream& os, const A<T>& a);
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const A<T>& a)
{
os << a.value;
return os;
}

int main()
{
A<double> a(1.23);
std::cout << a << std::endl;
}
647636:03/01/27 16:44
>>637
なはは…うっかり忘れてました。
その間についに VC++ に別れを告げる決意を固めて、試したのは g++ 上でした。

VC++ では通らないかもしれないです。
648638:03/01/28 01:03
>640
無事complex<double> とdouble間の計算が出来ますた。有難う
テンプレート引数の型を文字列リテラルとして取り出したいんですが
どうすればいいでしょう。つまりログとりたいんです

template<typename T>
class Hoge {
public:
 Hoge() {
  Log::debug("Hoge<T>::Hoge()");
 }
};

Hoge<int> hoge;

で Hoge<int>::Hoge() と表示してほしいんですが・・・
>>649
typeid(T).name()
>>649
typeid(T).name()
652651:03/01/28 03:25
>>650
ケコーン
それはconst char*でして、文字列リテラルではないかと・・・
コンパイル時に Hoge<int>::Hoge になって欲しいんです・・・
>>653
無理。
std::string でも使え。
ガビーン
あきらめます・・・
656 :03/01/28 17:55

"<" と ">" に挟まれた文字列を検索して格納したいのですが。
これで良いでしょうか?

{
    std::string text;
    std::string __text;
    std::string::iterator i_first;
    std::string::iterator i_last;

    i_first = __text.begin() + __text.find( "<", 0 ) + 1;
    i_last = __text.begin() + __text.find( ">", 0 );

    text.assign( i_first, i_last );
}
>>656
例えばこんなのはどうか。

std::string text;
std::string __text;
std::string::iterator i_first;
std::string::size_type st;

i_first = __text.begin() + __text.find("<") + 1;
st = __text.find(">") - __text.find("<") - 1;

text.assign(i_first, st);
これでもいい。
std::stringはイテレータよりもインデックスで扱った方が
扱いやすいようだ。

std::string text;
std::string __text("aaa<abc>def");
std::string::size_type st, st2;

st = __text.find("<") + 1;
st2 = __text.find(">") - __text.find("<") - 1;

text = __text.substr(st, st2);
文字列が"abd>efg<hijklmn"とかだと破綻しねぇか? 全部。
>>659
エラーチェックしてないから。したらしたなりになる。
>>656
boost::regex使えばいいのに。
662656:03/01/28 20:36
正規表現で探すのは後に実装する予定でした。
とりあえず抽出だけを考えてます
それで、関数を作ってみました。

const std::string Extraction
(
const std::string text,
const std::string text_open,
const std::string text_close
)
{
std::string output = "";
std::string::size_type position_open = 0;
std::string::size_type position_close = 0;
std::string::size_type position_target = 0;

position_open = text.find( text_open, 0 );
if( position_open == std::string::npos ) return ( const std::string )"";

position_close = text.find( text_close, position_open );
if( position_close == std::string::npos ) return ( const std::string )"";

position_target = position_open + text_open.length();

output.assign( text, position_target, position_close - position_target );

return ( const std::string )output;
}
663656:03/01/28 20:37
使用してみました

std::string t;
t = Extraction( "a<b<c<d", "<", ">" ); // 無
t = Extraction( "a<b<c>d", "<", ">" ); // b<c
t = Extraction( "a<b>c<d", "<", ">" ); // b
t = Extraction( "a<b>c>d", "<", ">" ); // b
t = Extraction( "a>b<c<d", "<", ">" ); // 無
t = Extraction( "a>b<c>d", "<", ">" ); // c
t = Extraction( "a>b>c<d", "<", ">" ); // 無
t = Extraction( "a>b>c>d", "<", ">" ); // 無

STL 初心者なもので、色々と不具合があるかもしれません。
みなさんどうもありがとうございました
>>662

これではいかぬか

const std::string Extraction
(const std::string& text, const std::string& text_open, const std::string& text_close)
{
std::string::size_type position_open = text.find(text_open), position_close, position_target;

if (
position_open == std::string::npos
|| (position_close = text.find(text_close, position_open)) == std::string::npos
|| (position_target = position_open + text_open.length()) > position_close
)
return std::string();
else
return std::string(text, position_target, position_close - position_target);
}
boost::shared_ptrのような非進入型参照カウンタを使ったスマートポインタって
スマートポインタ同士の直接代入はできるけど、
スマートポインタから生ポインタを取り出して、それを別のスマートポインタに入れると参照カウントの二重管理になって悲惨な結末になるんですよね。

んで、普段は可能な限りスマートポインタを使うことでどうにかなるんですけど、
一ヶ所だけ絶対にスマートポインタが使えないところがあって、
つまり this ポインタなんですけどね。

boost::shared_ptr< MyType > MyType::GetObject( std::string name )
{
 return boost::shared_ptr< MyType >( this->name==name ? this : new MyType( name ) );
}

みたいな必要があったとき、皆さんならどうしますか?
私はもうぜんぜん思いつかないんで進入型に切り替えるしかないかなぁとか思ってますが。
その場合MyTypeを管理している上位クラスが全部責任を持つ構造にする。
667デフォルトの名無しさん:03/01/31 23:37
STLportのhashって使ってみられた方いらっしゃいます?
>>667
hash_map ではなくて、ハッシュ値を計算する hash の方? 使った事はあるけど。
>>668
hashのアルゴリズムは処理系依存なんですよね。
どういう仕組みで発生しているのか興味があります。
>>669
> hashのアルゴリズムは処理系依存なんですよね。
STLport の hash の話をしてるなら、処理系非依存だが。stl/_hash_fun.h に
書いてあるから読んでみ。

ちなみにテンプレートクラスとして定義されているので、ユーザ定義クラスに対する
ハッシュ値は、自分で specialization しないと計算できない。
>>670

inline size_t __stl_hash_string(const char* __s)
{
_STLP_FIX_LITERAL_BUG(__s)
unsigned long __h = 0;
for ( ; *__s; ++__s)
__h = 5*__h + *__s;

return size_t(__h);
}

これでしょうか。割と簡単な事してるんですね。ありがとうございました。
LokiのVC6Port(↓)にReferredTypeやPointeeTypeを実装するのは
無理かなあ?
isEnumとisMemberFuncPointerは出来たので送ったら反映されたん
だけど誰かアイデアない?

http://fara.cs.uni-potsdam.de/~kaufmann/?page=lokiport
ファイルの内容を表示するプログラムを作ってみたのですが、
改行を表示してくれません。どこを直せば良いでしょうか。

int main()
{
std::ifstream ifs("copy1.cpp");

std::copy(std::istream_iterator<char>(ifs), std::istream_iterator<char>(), std::ostream_iterator<char>(std::cout));
}
>>673
std::istream_iterator<type>(i)は、i >> t を内部で実行しているため、
ホワイトスペース文字はスキップされて読み込まれない。
>>674
ありがとうございます♪
意外でした。std::getlineか何かで読み込んでみることにします。
>>675

std::noskipwsをストリームに食わせてやれば、ホワイトスペース
文字も読み込める。

int main()
{
std::ifstream ifs("copy1.cpp");

ifs >> std::noskipws;
std::copy(std::istream_iterator<char>(ifs), std::istream_iterator<char>(), std::ostream_iterator<char>(std::cout));
}
> ifs >> std::noskipws;

何か、「食わせてる」 って気がしないよな。
ちなみにそういう場合は[io]streambuf_iteratorを使ったほうが速いぞ、と。
某所で見かけた静的配列の長さを調べるコード。ちょっと感動した。

template< typename T, size_t N >
inline size_t length_of( T(&)[N] ) throw(){ return N; }

それを参考にした、静的配列の最後の要素を得るコード
template< typename T, size_t N >
inline T& last_element_of( T(&array)[N] ) throw()
{
 return array[N-1];
}
なるほどこれなら単純で良いね。

int main()
{
std::ifstream ifs("copy1.cpp");

std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(), std::ostream_iterator<char>(std::cout));
}
STLportって何がいいの?ラインセンスもアレだし。
682デフォルトの名無しさん:03/02/03 12:03
>>679
ちなみに某所ってどこよ?他にもお宝眠ってたりせんかの?
>>682
たぶん ttp://www.kmonos.net/wlog/23.php あたりか?
でもこれ自体は別に新しくもない話題だよ。
ttp://www.ganaware.org/D/diary/2000-07.html
684679:03/02/03 13:14
>>682
tp://www.issei.org/diary/ にて。
>>683
そーだったのか…
685682:03/02/03 14:15
>>684
なるほろthx!
>>683
まぁまぁそう言わんと。知らん人間にとっては新しくなくても十分面白かったんで。
>>684
その日記の元ネタは cuj web site の記事。URL を忘れたので元記事へのリンクを
張らなかったんだが、google に掛け合って見つけてきたよ。制限事項に関しても詳
しく書いてあるから、ざっと読んでおくと良いと思いかと。

http://www.cuj.com/articles/1999/9902/9902h/9902h.htm?topic=articles

これに関連した小ネタだと、std::for_each のような一定範囲を扱うアルゴリズムに
次のような多重定義をしておくってのもある。for_each や find_if は、コンテナ全部
に適用したいケースが多いから。

template <class T, class TFunc>
inline TFunc for_each(T& col, TFunc f)
{
  return std::for_each(col.begin(), col.end(), f);
}

template <class T, int N, class TFunc>
inline TFunc for_each(T (&ary)[N], TFunc f)
{
  return std::for_each(&ary[0], &ary[N], f);
}

template <class T, int N, class TFunc>
inline TFunc for_each(T const (&ary)[N], TFunc f)
{
  return std::for_each(&ary[0], &ary[N], f);
}
687デフォルトの名無しさん:03/02/03 23:42
lokiのSmartPtrを使ってるひとはいますか?
あれがもっとも汎用的でいいと思うのですが
なんでboostには含まれないのかな?
>>687
つかってまつ。gcc 2,95のバグに悩まされました。
>>687
いま、ちょうどboostのMLでLokiの人含めて色々議論してるようだから読んでみれば?
>>687
boost-mlでなんか今 auto_ptr みたいな挙動をどーするか
議論してるよ。boostに取り込まれる予定なはず。いつかは知らんけど。
691690:03/02/04 00:00
ぐはぁ、かぶった。逝ってきまふ・・・
>>691
逝かんで良いから、議論の流れをザクッと要約してくれると嬉しい。
693690:03/02/04 00:53
>>692
無理でふ。サラッと見ながら
「あー、なんかモメてるっぽいなぁ」
程度にしか読んでいないので・・・
「結論出たら結論だけ見ればいいや」
と思ってるんであんま(全然)流れ追ってないんですわ。

ちなみに今は配列のサポートでまた何やら議論してるみたい。
これも別にマトモに追ってないんですけど。
>>680
単純がいいなら、こっちにしとけば?
main()
{
std::ifstream ifs("copy1.cpp");
std::cout << ifs.rdbuf();
}
>>694
何と!簡単ですね!
それってどれくらいメモリ食うの?
>>686
参考になりました。Thanks!
>>696
「それ」ってなに?
>>699
なんで「メモリ食う」なんて思ったんだ?
ファイルの読み取りバッファと標準出力の
書き込みバッファくらいしか思いつかないんだが。
>>700
いや、内部的に何が起こるのかなと思って。
>>701
「内部的」なことは当然わからんが、
1文字ずつ読んだ場合に比べて余分に
メモリを必要とする理由はなにもない。
703デフォルトの名無しさん:03/02/05 15:24
低レベルな質問で申し訳ないですが,
binary_function<Arg1, Arg2, RetVal>にはoperator()
定義されてないんでしょうか?
cout << plus<int>()(2,3) << endl;
は上手くいくのに,
binary_function<int, int, int> fn = plus<int>();
cout << fn(2, 3) << endl;
は上手くいきません.
>>703
定義されてない。
operator()は仮想関数じゃないよ。
705703:03/02/05 15:46
では,関数オブジェクトを引数として渡したい場合は,
引数の型は何にしたらいいんでしょうか?
>>705
ふつうはテンプレートの型引数だな。
template<typename BinaryFunction>
void f(BinaryFunction fn);
707703:03/02/05 15:57
<algorithm>以下の関数でもそうしてましたが,
テンプレートで取り込もうとすると,
色々と面倒な事起こりませんか?
出来れば,引数として取り込みたいのです.
>>707
別に面倒なことなんかないが?
709703:03/02/05 16:02
すいません.↑意味不明でしたね.
様はtemplateは使わずに,
void f(binary_function<int, int, int> fn);
みたいな感じで使いたいのです.
binary_functionはlessやらplusやらの基底クラスらしいですが,
共通に使われるであろうoperator()を仮想関数として定義
してないんじゃ使えないですね.
引数としてこのクラスの関数オブジェクトを読み込む場合,
この代わりに何を基底クラスとして使うべきなのでしょうか?
710703:03/02/05 16:03
>>709
templateを使って定義すると,
ソースコードをいちいちincludeしないといけなくなりませんか?
>>709
そんな方法はない。お前はbinary_functionの存在理由を大幅に誤解している。
>>709
そうなると、基底クラスじゃぁないが、boost::functionなんだろうなぁ。
>>709
binary_functionはtypedef導入用のテンプレートであって、
多態で使うことを目的としたものじゃない。

> void f(binary_function<int, int, int> fn);
何故templateにしないでこうしたいのかがよく
わからんが、とりあえず boost::function 使え。
714703:03/02/05 16:12
>>712
STLじゃ無理なんですね.
>>709
binary_function は引数、戻り値の型を class 内の typedef として定義するための
クラス。それ自身はなんの機能も持たない。

Generic Programming あたりを読んでお勉強するのが良いと思われ。
BCCで、
テンプレート引数の整数はunigned int ではだめで、特別化がおきず、intにしなくてはいけません。
これってC++の仕様ででしょうか?整数引数単独のテンプレはOK。

#include<iostream>
template<class T,unsigned int Sz>
struct vector{
public:
vector(){std::cout << "Standard" <<std::endl;}
};
template<class T>
struct vector<T,3>{
public:
vector(){std::cout << "Special" <<std::endl;}
};

int main(){
vector<double,1> v1;//Standard
vector<double,3> v3;//Specialになってほしいが・・・
return 0;
}
>>716
BCC5.6.2だとちゃんとSpecialになるよ。
>>717
お、そうですか・・・。BCC5.5のバグなんですね。ありがとうございます。

VC++7.0 で、以下の式が正しく通るんだけど…

 // ↓LokiPort for VC++7.0
 Loki::SmartPtrDef<MyClass>::type sp( new MyClass );
 sp[ 2 ];

犯人は特定できたけど、この仕様のおかげで、
自作の添え字演算子を持つポリシーが使えないじゃないかっ!


>>719

音無しくboost::shared_arrayにするよろし
>>719
犯人は?
ヤス
>>722
いつのネタだよ。
ポートピア連即殺人事件の中の人も大変だな。
>>719
operator Tester*()
こいつのおかげで、operator[] が曖昧だといわれてしまう。

>>723
中の人な(ry
725722:03/02/07 09:44
>>723
通じるなら立派なネタじゃないか
ザクの犯人はシャア
templateの型推測のアルゴリズムが今ひとつわかりにくかったので
良書を探していたら、C++Primerが目に止まった。

この本はC++初心者用だからと今まで目もくれなかったが、今日
何気に立ち止まって読んでみると、templateについてじつに詳しく
書いてある。これだけでも買う価値があると思い、速攻レジへ。

本の厚さに圧倒されつつも、読んでいます。アルゴリズムについて
も相当詳しい解説があります。でもアルゴリズムは一通りやった
んだけどな。
728724:03/02/07 18:24
>>724>>719 へのレスは、>>720 へのレス
729デフォルトの名無しさん:03/02/08 00:14
treeコンテナ でおすすめなものないでしょうか?
>>729
二分木コンテナ?何に使うの?
>>729
set とか map とか、内部実装的には tree になってるよ。
ちなみに、STL で使われてる平衡木アルゴリズムは二色木(red black tree)。
732デフォルトの名無しさん:03/02/08 02:36
>>730
バランス木または多分木のコンテナが欲しいです。
ゲームの探索に使おうと思ってます。
>>732
要するに、そのゲームに特化した最適な構造の木を使いたいってこと?
そんな特定用途向けのライブラリ、早々転がってないぞ。

とりあえず、STL ので我慢して作って、
パフォーマンス的にどうしても必要になったら改めて自作しろ。
2つの型が同じかどうか判定することってできるでしょうか

template<typename A, typename B>
bool IsSameType();

いろいろ考えましたが思いつきませんでした・・・
>>731
std::map をどうやって「木として」使うんだ?

>>729
平衡木なら http://www.essemage.com/aapl/ とかが有名どころではなかろうか。
多分木はあんまり見たこと無いなぁ。

>>734
template<typename A, typename B> struct ist { enum{ val = 0 }; };
template<typename A> struct ist<A,A> { enum{ val = 1 }; };

template<typename A, typename B>
bool IsSameType() { return ist<A,B>::val; }
>>729
http://www.damtp.cam.ac.uk/user/kp229/tree/

ってなモノがある。昔boost-mlに流されたけどどーなったんだっけか?
まぁただGPLという最大の罠があるわけだが。
class A1;
class A2;
...

class B {
private:
A1 a1;
A2 a2;
...
public:
};

の時にa1、a2に[]を使ってアクセスする方法はないでしょうか?
#define private public
739738:03/02/08 23:17
あ、違った。失礼。
まぁ、operator[]でも定義しなさいってこった。
740737:03/02/08 23:24
A1,A2,・・・がA_Baseから派生していて、a1,a2が配列要素になっていたら
[ ]を定義できるのですが、この場合どうやったらいいか分かりません。
また上記の場合派生して加えた関数にアクセス出来ません。templateを使って旨く出来ないでしょうか?
741738:03/02/09 00:25
ん?
B::operator[]
をテキトーに定義してやるんじゃマズいの?
なんか良く意味が分かんないんだけど。
>>737
B b; があって、
b[0]がa1、b[1]がa2を返すとか、そういう事かい?
743737:03/02/09 00:44
switchでべた書きでは無くて何か巧くできないものかと思いまして。
744737:03/02/09 00:46
>>742 そんな感じです。
B b;
で、b[0].func(hoge) とか出来ない物かと。
>>744
A1とA2が継承関係にでもないと、一つの[]でA1とA2両方返すのは
難しくないかい?
なんかすっきりせんな。

struct A1 {
virtual void func() { std::cout << "A1" << std::endl; }
};

struct A2 : public A1 {
void func() { std::cout << "A2" << std::endl; }
};

struct B {
A1 a1;
A2 a2;
A1* operator[](int i) {
if (i == 0) return &a1;
else return &a2;
}
};

int main()
{
B b;
b[0]->func();
b[1]->func();
}
747738:03/02/09 01:10
あぁ、そっかそっか。
>>744
で、[]の引数はやっぱコンパイルタイムには決まらんの?
決まるんなら boost::tuple みたいな事すれば
b.get<0>().func(hoge)
なら出来る・・・かな?
friendとtemplateの特殊化を使って実装しようかと試みたが、[]は
メンバ関数でないとだめみたいだしなあ。friend使えたら何とか
なったかもしれんのだが。
だめだこれでも継承関係しか受け付けない。

struct A1 {
virtual void func() { std::cout << "A1" << std::endl; }
};

struct A2 : public A1 {
void func() { std::cout << "A2" << std::endl; }
};

struct B {
A1 a1;
A2 a2;
A1& operator[](int i) {
if (i == 0) return a1;
else return a2;
}
};

int main()
{
B b;
b[0].func();
b[1].func();
}
可能だとしても、そんなオーバーロードは認めたくないね。
751737:03/02/09 01:48
皆さんありがとうございます。難しいのですね。
>>747 さんの方法も含めて考えてみます。
出来るだけpublicにはしないように頑張っているのですが、初心者には中々難しいです。
struct A1 {
void func() { std::cout << "A1" << std::endl; }
};

struct A2 {
void func() { std::cout << "A2" << std::endl; }
};

struct B {
A1 a1;
A2 a2;
void* operator[](int i) {
if (i == 0) return &a1;
else return &a2;
}
};

int main()
{
B b;
reinterpret_cast<A1*>(b[0])->func();
reinterpret_cast<A2*>(b[1])->func();
}
派生クラスの関数呼び出すんなら、配列(的)にする意味あるの?
754737:03/02/09 02:10
>>753
B b[100];
としたいので、b[1][1].func(hoge)って呼べた方が楽だなぁと思ったのです。

>>752 ありがとうございます。参考にさせて頂きます。
>>754
> としたいので、b[1][1].func(hoge)って呼べた方が楽だなぁと思ったのです。
激しく読みにくいコードのような気がするが…

面倒でも、素直に「役割」を反映したメソッドを書いて deletate した方が
良いと思うぞ。
756737:03/02/09 02:25
>>755 そうですか・・・。頑張ってみます。
>>734
> 2つの型が同じかどうか判定することってできるでしょうか
boostの、<boost/type_traits.hpp>をインクルードして、
boost::is_same<T, U>::value
でいけるようだが、中身を見ても何をしているのか解らなかった・・・。
758729:03/02/10 09:30
>>730-736
結局、色々やるには自分で作った方がいいという結論になったのですが、
上記の物は参考にはなりました。
ありがとうございました。

//構造的にはこんな感じ
template <typename _Elem> class tree
{
tree *parent;
list<tree*> m_child;
_Elem m_element;
};

759デフォルトの名無しさん:03/02/10 10:48
spirit & phoenix
ホントにキタ━━━━━━(゚∀゚)━━━━━━ !!!!!
760デフォルトの名無しさん:03/02/10 18:11

スレ違いかもしれんけど、いい知恵を貸してください。

COMなんかで使用する BSTR は ATLインターナル等を読む限り、
「長さをプレフィックスとするOLECHAR型の文字列」だそうです。
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
で、これを std::basic_string で表現したいと思い、
char_traits をいじり始めたのですが、
「長さをプレフィックスとする」の部分で躓きました。

このような長さを先頭にもつ文字列を basic_string で表現する
うまい手段があったら教えてください。
>>760
basic_stringで表現するより、
別のクラスにしてbasic_stringと相互?変換できるようにするほうが楽じゃないの?
760はマルチ
763デフォルトの名無しさん:03/02/10 21:28
ここでシェルスクリプトのこと聞いてもいいでつか?
それとももっと適した板があるなら教えてくだたい
>>763
シェルスクリプトならUNIX板とかLinux板とかでないかね
>>760
どっちみち、一般のヒープ管理関数じゃなくてSysAllocStringで確保しなきゃいけないわけだし、
プレフィックス部分はポイントされている番地より「前」に存在するわけだし、
いじるならchar_traitsじゃなくてallocatorのほうではないか。
char_traitsはそのままstd::char_traits<wchar_t>でいい気がする。
void wfstream::open
(const char* __s, ios_base::openmode __mod = ios_base::in)

ファイル名が、なぜ wchar_t でなく char なのでしょうか?
767デフォルトの名無しさん:03/02/12 20:36
VC7で以下が通らないのはVC7のバグ?それとも俺の思い違い?

#include <iostream>
#include <memory>

class A
{
public:
void Print(void){ std::cout << "OK" << std::endl; }
};

int main()
{
std::auto_ptr< A > ptr( new A() );

void (A::*method)(void) = A::Print;
(ptr->*method)(); // ここや

return 0;
}

ptr->* って、std::auto_ptr<A>型についてのメンバ関数へのポインタを
探すことにならんか?
>>767
ptrはA型へのポインタだから、当然Aの中にmethodというメンバ
がないとエラーになる。

struct A {
int i;
}

std::auto_ptr<A> ptr(new A);
int j;
ptr->j;

としているのと極端に言えば同じ。
スマソ>>769は間違いです。見逃してくれ。
A* a;
(a->*method)();

としたら通るね。ということは、std::auto_ptrの->演算子の多重定義
の問題なのだろう。
->の先がメンバー関数へのポインタだった場合、正常に解釈して
くれないのでは。
772766:03/02/12 21:32
どうか見捨てないで下さい
773デフォルトの名無しさん:03/02/12 21:34
((*ptr).*method)()
にしれ
>>767
auto_ptr<> には operator->* というメンバ関数はないので
どのコンパイラでも無理だ。
あっそうか!->という演算子ではなくて->*という演算子なのだね。
((*ptr).*method)() が通るという事は、.*は定義されているのかな。
>>775
(*ptr)の時点で A* になってる
あ、ちがうか、A&か。
>>776>>777
なるほどよく理解できました。
そしたら、((*ptr.get()).*method)();が通る理由も理解できます。
779767:03/02/12 22:44
>>773

ってゆーかその手に気付かなかった自分が恥ずかしいよ。
->が定義されてるなら->*も自動だと思ったんだけどそうじゃなかったんだな。
ためしに->*を定義してみたらなかなか面白いことになったけどいまいち使いどころがわかんね。
->* って定義できたっけ?
>>780
できるよ。
でも逆に .* は定義できないんだよね。
->*が定義できるのだから、今度の新しい標準C++はstd::auto_ptrにも
定義して欲しいものだ。
operator->* をユーザー定義して普通の ->* と同じ動作をするものを
作ろうと思ったら、boost::bind 完全再生産、くらいのレベルで大変なんだけど、
なんであんな規格なんだろう。
オーバーロードできない演算子って、
. .* :: ?: sizeof # ##
で全部?
スマートポインタが->*をサポートするには何を返せばいいんだ?
->が返すのは生ポインタだよね。
>>784
typeid
>>785
こんな感じかと

#include <iostream>
#include <functional>

class A
{
public:
int b;
void hoge( int v ){ std::cout << b << v << std::endl; }

public:
template< typename type >
type& operator ->*( type A::*p ){ return this->*p; }
template< typename type >
std::binder1st< std::mem_fun1_t< type, A, int > >
operator ->*( type (A::*p)( int ) ){ return std::bind1st( std::mem_fun1( p ), this ); }
};

int main()
{
A a;
int A::* pb = &A::b;
a->*pb = 10;
void (A::*phoge)( int ) = A::hoge;
(a->*phoge)( 20 );
}
>>784
throw 演算子もできないような気もするが……できるならサンプルプリーズ
789785:03/02/14 04:00
>>787 にゃるほど。少し分かりました。thx.
>>787
凄すぎ。このコードを理解するように努めてみます。
791784:03/02/14 14:35
>>786
忘れてました。ども。

そういえば、std::XXX_cast<> 達はキャスト「演算子」なのですかね。
だとしたらオーバーロードできない、でいいと思うけど。

>>788
手元のプログラミング言語C++ 第2版では、throw は演算子じゃなくて式(の一部)のようです。

第3版がほすぃ・・・。
792デフォルトの名無しさん:03/02/15 07:19
listのeraseで自分のコンテナ以外の反復子を削除できるようなのですが、
この使用は抑止した方がいいのでしょうか?

#include<list>
#include<iostream>
#include<string>
#include<vector>
using namespace std;

int main()
{
list< vector<string> > a,a2;

vector<string > s,s2;
s.push_back("111");
s2.push_back("222");

a.push_back(s);
a2.push_back(s2);

a.erase(a2.begin()); //aのeraseでa2の反復子を削除する。
//list<T>::eraseのソースをみると
//_Mysize--;となっているが、
//_Mysize=size();としないと矛盾しないか?(debbugerのsizeも0,1になってる)

cout << "a size:" << (*(a.begin())).size() << std::endl;
cout << "a2 size:" << (*(a2.begin())).size() << std::endl;//a2の要素は削除されてる
//これはbegin()とend()から計算してるから大丈夫。

cout << "*a.begin():" << *(*(a.begin())).begin() << std::endl;//111
}
>>792
実装的にその方が楽なんよ。
STLは計算効率至上主義だからそういう風になってるんだと思われ。

ほんとはそういうまねは出来ない方がいい。

794792:03/02/15 15:51
>>793
ちと勘違いしてたんで、修正した。
サイズ等の状態数を管理するのって危険が伴うのにそれを完全に排除してない
方が悪い気がするんだけど。

//上と同じ

int main()
{
list< vector<string> > a,a2;

vector<string > s,s2;
s.push_back("111");
s2.push_back("222");

a.push_back(s);
a2.push_back(s2);

a.erase(a2.begin()); //aのeraseでa2の反復子を削除する。
cout << "aのeraseでa2の先頭の反復子を削除する" << std::endl;

cout << "a.size() :" << a.size() << std::endl; // VC 0 ,GCC 1
cout << "a2.size():" << a2.size() << std::endl; // VC 1 ,GCC 0

cout << "(*a::begin()).size()) :" << (*(a.begin())).size() << std::endl; // VC 1 ,GCC 0
cout << "(*a2::begin()).size()):" << (*(a2.begin())).size() << std::endl; // VC 1 ,GCC 0

cout << "*(*(a.begin())).begin() :" << *(*(a.begin())).begin() << std::endl;//111
//cout << "*(*(a2.begin())).begin():" << *(*(a2.begin())).begin() << std::endl;//
}
795794:03/02/15 16:06
>>794
よくみたらミスってました...。
cout << "(*a::begin()).size()) :" << (*(a.begin())).size() << std::endl; // VC 1 ,GCC 1
cout << "(*a2::begin()).size()):" << (*(a2.begin())).size() << std::endl; // VC 0 ,GCC 0
であってると思います。
>>794
Sequence::erase の Precondition を破っているので、
未定義動作でしょうがないと思われ。
797デフォルトの名無しさん:03/02/16 02:30
STLport 使ってて(iostreamは使用せず)
ICU使いたいんですけど
STLportのスタティックライブラリにする必要あります?
経験者の方教えてください。
798794:03/02/16 08:16
>>796
同じ型のコンテナ内の反復子を矛盾なく削除できる関数として
機能したほうがいいと思うんだけど。
その代わり、多少パフォーマンスは下がってしまうか。

コンテナが反復子の状態数を保存してるときは
反復子を操作(削除)するときに
管理しているコンテナに通知して処理するほうが望ましい結果が得られる。
799デフォルトの名無しさん:03/02/16 09:03
Boostsを使いたいのですがどこか日本語で詳しく解説してあるサイトか本はありませんか?
あったら教えてください。
>>798
iteratorは基本的に自分が属するContainerがどれであるかを知らないし、
Containerは基本的に自分の上のiteratorがどこかに存在しているかどうかを
知らないし、
algorithmは自分が操作する対象がどんなsequenceであるかを知らない…

という形にすることで可能な限り一般性を高める、というのが
STLの方向性だと思うので、↓の是非は別にして、
> コンテナが反復子の状態数を保存してるときは
> 反復子を操作(削除)するときに
> 管理しているコンテナに通知して処理するほうが望ましい結果が得られる。
これはSTLに求める性質としてはお門違いではないかと。
803799:03/02/16 09:28
>>800 , 801
ありがとうございます。
自分でさがせ、殺すぞ、とか言われるかと思いましたがやさしいですね。
804794:03/02/16 12:40
>>802
一般的な反復子にはもちろん同意だが、
コンテナ内のtypedef(または定義)されたiteratorを
削除するときは違う。
a.insert(a2.begin()) -> は問題ない
a.erase(a2.begin()) -> a2側に通知が必要

STLの性質を求めてるんじゃなくて、
結果が正しくなることを求めてる。
使い方が間違ってるのに結果が正しくなるのは無理だと思われ
>>804
自分で勝手に自分がどのコンテナオブジェクトに属しているかを知っている
イテレ−タを使ってアクセスされるリストクラスでも作って使っとけアホ。
とりあえず話を>>792に一旦戻すと、
> listのeraseで自分のコンテナ以外の反復子を削除できるようなのですが、
自分のコンテナ以外の反復子を指す要素は削除「できない」。実装によっては
たまたま削除されてしまうかもしれないが、その辺りの動作は未定義。

それをふまえて。

> a.insert(a2.begin()) -> は問題ない
a.insert(a2.begin, value) か? a.erase(a2.begin()) と同じ程度には問題あるだろう。

> 結果が正しくなることを求めてる。
sqrt( "弐" ) とやったら "1.41421356" と返すのが正しい結果だ、
と主張してそれを求めてるのに等しいことは自覚してるか?

無論、sqrt( "弐" ) と同じでコンパイルエラーになるとか、最悪でも
実行時エラーになったら嬉しいのは確かだし、(だからSTLPortの
Debug版とかはかなり重宝されている。) staticメンバ関数を使って
list<T>::erase(a2.begin()) と書けるiterator/container はそれなりに便利だろう。
が、それはSTLの範疇じゃない。
808807:03/02/16 14:06
×反復子を指す要素
○反復子の指す要素
809デフォルトの名無しさん:03/02/16 14:07
>>806
ひとこと余計なんだよ。
カスが。
810デフォルトの名無しさん:03/02/16 19:14
STL含んでいるObjectを、Exe <-> Dll 間で使用していると
保護違反が発生するのですが、STLはExeをまたがって使用できないのですか?

環境は .Net STLはMS製です。
>>810
MSの作るのDLL/EXEは、MSVCRT.DLLを使わない限り、ヒープを個別に
持つことになる。片方でnew/mallocしたものを他方でdelete/freeすると
当然おかしなことになる。
MSVCRT.DLLを使うか、またがってnew/deleteをしないよう
気をつけるしかない。
812デフォルトの名無しさん:03/02/16 19:54
重複項を省くためにsetを使っているですが、
list<N>::iteratorの比較をしたい場合には、どのようにしたら良いのでしょう?

list<N>::iterator il; // Nは適当なクラス
set<list<N>::iterator> lset;
lset.insert(il); // 必要なilを適宜追加する。ここでの重複を省きたい。

(とりあえずコンパイル通すために)以下のようにiteratorの比較をしています
bool operator < (const std::list<N>::iterator lhs, const std::list<N>::iterator rhs)
{ return &(*lhs) < &(*rhs); }

g++(2.96〜3.2)では通るのですが、Intel Compiler(icc)では、
# error: no operator "<" matches these operands
# operand types are: const std::list<N, std::allocator<N>>::iterator
# < const std::list<N, std::allocator<N>>::iterator
とはじかれてしまいます。

どうすれば解決するかご指摘いただけないでしょうか?
template< typename Iterator >
struct compare_dereferenced_address : std::binary_function< bool , Iterator , Iterator >
{
  bool operator () const ( const Iterator& lhs , const Iterator& rhs )
  { return &(*lhs) < &(*rhs); }
};

set<list<N>::iterator,compare_dereferenced_address<list<N>::iterator> > lset;

Interl Compiler 持ってないから、実験はできないけど、
とりあえず行儀よくしてやったら治らないかね?
814sage:03/02/16 21:01
>>811
レスありがとうごさいます。
>またがってnew/deleteをしな気をつけるしかない。
この修正してきます
815812:03/02/16 21:13
>813
治りました。ありがとうございます。

binary_functionにあまり馴染んでないせいか(必要にかられて本を調べる程度)
set<list<N>::iterator,compare_dereferenced_address<list<N>::iterator> > lset;
こんな風に宣言できることすら思いつきませんでした。
816デフォルトの名無しさん:03/02/16 21:31
boostとstdの function の Resultの位置は逆になってたような...。
817813:03/02/16 21:46
コンパイルが通るだけに、恐ろしい罠だのぅ。
818812:03/02/17 04:49
解決したつもりになっていたのですが、、、

set<list<N>::iterator,compare_dereferenced_address<list<N>::iterator> > lset;
とすると確かに通るのですが、挙動不審です。
どうも元の set<list<N>::iterator> との型の互換で失敗しているようです。
この辺のデバッグが非常に面倒なプログラムなので、
できれば素の、set<list<N>::iterator>のまま通したいところです。切実に、、

せっかく
bool operator < (const std::list<N, std::allocator<N> >::iterator lhs,
const std::list<N, std::allocator<N> >::iterator rhs)
{ return &(*lhs) < &(*rhs); }
と、operator用意しているのに、何で使ってくれへんの? と悲鳴をあげつつ
以下がエラーメッセージ全文となります。うざったくてすんません。
どうか、もちょっとだけアドバイスを下さいませ。

/opt/intel/compiler70/ia32/include/functional(134): error: no operator "<" matches these operands
operand types are: const std::list<N, std::allocator<N>>::iterator
< const std::list<N, std::allocator<N>>::iterator
return (_Left < _Right);
^
detected during:
instantiation of "bool std::less<_Ty>::operator()
(const _Ty &, const_Ty &) const [with _Ty=std::list<N, std::allocator<N>>::iterator]"
at line 471 of "/opt/intel/compiler70/ia32/include/xtree"

instantiation of "std::_Tree<_Traits>::_Pairib std::_Tree<_Traits>::insert(const std::_Tree<_Traits>::value_type &)
[with _Traits=std::_Tset_traits<std::list<N, std::allocator<N>>::iterator,
std::less<std::list<N, std::allocator<N>>::iterator>,
std::allocator<std::list<N, std::allocator<N>>::iterator>, false>]"
> set<list<N>::iterator,compare_dereferenced_address<list<N>::iterator> > lset;
> とすると確かに通るのですが、挙動不審です。
> どうも元の set<list<N>::iterator> との型の互換で失敗しているようです。

失敗じゃネェよ。そいつらは違う型だ。
set<list<N>::iterator>を使ってたところで全部同じ型を使うように汁。
>>818
多分
 template<typename T> void function( tmpl<T> t ) { ... }
という定義があれば tmpl<T> t; function(t); で見つけられるけど、
 template<typename T> void function( tmpl<T>::type t ) { ... }
では tmpl<T>::type t; function(t); では見つからないはず。

# スマートポインタを ptr<T>::shared とか ptr<T>::auto とか ptr<T>::locked
# とか書きたいけど書けねぇなぁ、という議論で見かけた気がする。

ので素直に、
1: set<list<N>::iterator> を(名前は適切なものをつければいいが) set_of_N_iter に置換
2: typedef set<list<N>::iterator,compare_dereferenced_address<list<N>::iterator> >
    set_of_N_iter;
しとけ。

あるいは、iteratorの比較関数をtemplateにしないで
bool operator<( const list<N>::iterator& i, const list<N>::iterator& j ) { ... }
と一個一個書いていけばいいような気もするが。
821812:03/02/17 13:28
>819
>set<list<N>::iterator>を使ってたところで全部同じ型を使うように汁。
ごもっともです。
それでうまくいかなかったのは、やはり元のコードがbuggyだったせいかと。

>820
>bool operator<( const list<N>::iterator& i, const list<N>::iterator& j ) { ... }
>と一個一個書いていけばいいような気もするが。
これはどうも無理でした。

>では tmpl<T>::type t; function(t); では見つからないはず。
つまり、見つけられた(コンパイラ)の方がたまたまだったというわけでしょうか……

>ので素直に、 (中略) しとけ。
はい、そうしますわ。こつこつバグ治します。
どうでもいいけど、
ttp://groups.yahoo.com/group/boost/files/
とか見ていると、smart_ptr とか singleton とか
いい感じに Loki を取り込んでいってますな。
あと、次期 boost::lexical_cast 萌え

ところで、ここのコードって勝手に使っていいのかな?
>>821
素朴な疑問なんだけどさあ、iteratorってお互いの大小関係って
比較できたっけ?
==か!=でしか比較できなかったような気がするんだが。
それから、std::setの比較基準なんだけど、
1.std::set<Elem, Op>
2.std::set c(Op)
のどちらかでしか比較基準は指定できないよ。これを使わず
operator< を定義しても使ってはくれない。
>>823-824
> 素朴な疑問なんだけどさあ、iteratorってお互いの大小関係って
> 比較できたっけ?
だから812氏は苦労して { return &(*lhs) < &(*rhs); } なんて奇怪な
比較関数を作ってるんじゃねーの?

> のどちらかでしか比較基準は指定できないよ。これを使わず
> operator< を定義しても使ってはくれない。
set<T> とやったら比較ポリシーは std::less<T> になるから、
operator < が呼ばれる。つーか、キミ、勉強し直せ。
826820:03/02/17 20:50
>>821
追実験。。
> >bool operator<( const list<N>::iterator& i, const list<N>::iterator& j ) { ... }
> >と一個一個書いていけばいいような気もするが。
Comeau のオンラインコンパイラで試してみたら、
 namespace std {
  bool operator<( const list<int>::iterator& i, const list<int>::iterator& j ) { ... }
 }
とstdの中に突っ込んで置いたら一応コンパイルは通ったぞい。
猛烈に行儀が悪いので、止めた方が無難だが。
それがランダムアクセスイテレータなら大小関係の比較できる。
828812:03/02/17 22:02
>826
通りました! まさにピンポイントなアドバイス!
>猛烈に行儀が悪いので、止めた方が無難だが。
よそのコンパイラでお行儀悪くするためにはコツが必要なのですね。
ありがとうございます。

>827
なるほど。const list<N>::iteratorではなく、const vector<N>::iteratorの場合、
operator < を作る必要がなかったので不思議に思っていました。
勉強になりました。
829デフォルトの名無しさん:03/02/19 01:45
boostやSTLportのtype_traitsをユーザー定義型で特殊化するサンプルってありますか?
830デフォルトの名無しさん:03/02/21 05:05
次期vsはC++標準準拠度があがるみたいだけど
もうstlport使わなくてよくなるかな
もしかしたらVCもSTLport標準装備だったりして。
STLの実装がいくつもあってもあんまりいいことないよね
そろそろSTL開発会社も自然淘汰の時期だ。
managed C++ が多重継承できませんから。
stl なんか使いませんとも。
835デフォルトの名無しさん:03/02/21 14:25
2つのvectorがあって、1方にだけ含まれる要素を
抜き出すにはどうすればよいですか?

片方に含まれる、両方に含まれる、どちらにも含まれる、で
処理を分けるようなこともしたいです。
836デフォルトの名無しさん:03/02/21 14:35
>>835
ソート済みなら
std::set_union()
std::set_intersection()
std::set_defference()
が使えるかと。
>>835
片方にのみ含まれる - std::set_difference()
どちらにも含まれる - std::set_intersection()
両方の集合の和 - std::set_union()

但しこれらのアルゴリズムは必ず std::vectorを sort() してから
呼び出さなければならない。
ケコーン(w
839836:03/02/21 14:42
親切度低いぶんだけ早かったな俺(w
840仕様書無しさん:03/02/21 15:45
簡素な即レスと、丁寧な遅レスはどっちがより親切だろう?
>>840
両方あった方が良い(w
>>834
勘違いしている馬鹿発見。
843デフォルトの名無しさん:03/02/25 22:32
低レベルな質問で恐縮ですが
VC7にSTLportを導入した、つもりなんですが
どうも上手くいっていないみたいです。

ちゃんとSTLportが使われているかチェックする方法はないですか?

インクルードディレクトリを切り替えてlistの性能比較とかしても差がないし、
iostreamもSTLport版を使うようにし他場合、
#define _STLP_USE_DYNAMIC_LIB してできた実行ファイルを
Dependency Walkerで調べたらstlport_vc745.dllが表示されると
思っていたんですが、表示されませんでした。思い違いでしょうか?
インストールが上手くいっていないだけですか?
>>843
std の変わりに _STL ネームスペースを使って正常にコンパイル
できるかどうかチェックする。
845843:03/02/25 22:50
>>844
コンパイルできませんでした(泣
導入からやり直します。ありがとうございました。
>>845
SGI系のアダプタである _STL::compose1 とか _STL::compose2 が
コンパイルできるか確かめてみる方法もあるよ。
847デフォルトの名無しさん:03/02/26 00:00
std::vector x(10);
for(int i=0;i<10;++i) cin >> x[i];

を for で回さないでなんか algorithm 使って出来ないですかね?

std::vector x(10);
std::transform(x.begin(), x.end(), x.begin(), bind1st(std::mem_fun(&std::istream::operator>>), &std::cin));

で逝けるかなぁと思ったんですけど、
no matching function for call to `mem_fun(<unknown type>)'
と gcc-3.2.1 に言われてしまって…
まぁ完全に趣味なんで別に for で回せばいいんですけどね。
>>847
#include <iterator>
std::copy_n( std::istream_iterator<T>(cin), x.size(), x.begin() );
849848:03/02/26 00:08
って、copy_n ってもしかしたらSGI拡張だったかも…。
>>848
やってみたけど11個数字を入れないと終了しないよ。
STLport。
>>847
多分それがだめなのは、operator>>の戻り値型がstd::istreamだから
だろう。
>>847
ファンクタを作ったらだめかい?

template <typename T>
struct input {
T operator()(T& t) {
std::cin >> t;
}
};

int main()
{
std::vector<int> x(10);
std::transform(x.begin(), x.end(), x.begin(), input<int>());
std::copy(x.begin(), x.end(), std::ostream_iterator<int>(std::cout, " "));
}
853848:03/02/26 00:24
>>850
おー、ほんとだ。istream_iterator って operator* じゃなくて
コンストラクタと operator++ のタイミングで読まれるのか。使いにくいな。
スマソちょっと修正。

template <typename T>
struct Input {
T operator()(T& t) {
std::cin >> t;
return t;
}
};
入力にtransformはねぇだろ。

template< typename T >
struct input_from_cin
{
 T operator () ()
 {
  T temp;
  cin >> temp;
  return temp;
 }
};
int main()
{
 vector< int > v;
 generate_n( back_inserter( v ) , 10 , input_from_cin< int >() );

 copy( v.begin() , v.end()
    , ostream_iterator< int >( cout , " " ) );
}
856847:03/02/26 02:02
なるほど、皆さんありがとです。

>>848
copy_n は知らなんだです。gccのSTLにはあるみたいなんで良さそうですね。
でも確かに >>853 のような事に

>>851
それだと <unknown type> なんですか?そもそもこのエラーメッセージが良く分からんっす。
ちゃんと iostream は include してるから未知って事は無いと思うんですが…

>>852
まぁもちろんファンクタ作ればいいんですが、なんとなく一行野郎で行きたかったんで…

>>855
そうなんですが、一行野郎を目指したら個数を指定する為に無理矢理行き着いたのが
transform でして…可読性はゼロですけどね(w
for_each( v.begin(), v.end(), cin >> boost::lambda::_1 );
とか言ってみる。
>>857
(・∀・)ソレダ!!
859847:03/02/26 03:00
>>857
基本を忘れてますた…(w
# 基本か?
lambdaはなぁ・・・。
どうしてもランバダと読んでしまう。
862デフォルトの名無しさん:03/02/26 22:03
ランバダ算法騎士団
863tantei:03/02/26 22:05
★あなたのお悩み解決致します!!
●浮気素行調査
彼氏、彼女、妻、夫の浮気を調査致します!!
●盗聴器盗撮機発見
あなたの部屋に誰かが仕掛けているかも!!
●行方調査
行方不明になっている家族の消息を調査致します!!
●電話番号から住所割り出し
一般電話、携帯から住所を割り出し致します!!
●ストーカー対策
社会問題ともなっているストーカーを撃退致します!!
その他人生相談からどんなお悩みでも解決いたします!!
 直通  090−8505−3086
URL  http://www.h5.dion.ne.jp/~grobal/
メール  [email protected]
   グローバル探偵事務局 

★あなたのお悩み解決致します!!
●浮気素行調査
VB、JAVA、C#、COBOLの浮気を調査致します!!
●トロイ、ウィルス発見
あなたのプログラムに誰かが仕掛けているかも!!
●行方調査
行方不明になっている変数の消息を調査致します!!
●関数名からアドレス割り出し
.dll、.objからアドレスを割り出し致します!!
●バグ対策
社会問題ともなっているバグを撃退致します!!
その他設計相談からどんなお悩みでも解決いたします!!
 直通  http://pc2.2ch.net/tech/
URL  http://www.2ch.net/
メール  [email protected]
   2ちゃんねるプログラム板 

865STL初心者:03/02/27 13:40
vector<bool> は使うな という話を小耳にはさんだのですが、ほんとうでしょうか?
866デフォルトの名無しさん:03/02/27 13:55
boolのvectorとして使うつもりならば本当です
>>865
std::vector<bool>は過去の実装の遺物です。
固定でもよければstd::bitset、可変長が必要ならboost::dynamic_bitset
を使いましょう。
別に使ってもいいと思うよ。
ただし普通のvectorだと思って使うと細かいところで問題が起こる。
あと1要素が1bitで実装されてる保証はない。
>>865
bool型へのポインタが取得できません。
870STL初心者:03/02/27 16:54
>>867
固定長じゃないんですよー
>可変長が必要ならboost::dynamic_bitset
情報どもです。あとで調べます。
>>868
>ただし普通のvectorだと思って使うと細かいところで問題が起こる。
「細かいところ」って具体的にどんなことなんでしょう?
ビットにパックされているために bool *p = &vecBool[x]; とかができないとか?
push_back(), insert(), erase() と 値の参照、設定さえできればよいのだが
このあたりのことを詳しく説明したドキュメントってどこかにないのかなぁ
それともSTLのソースを読むしかないの?
871STL初心者:03/02/27 17:03
VC++6.0 を使っているのですが、ソースを読んだり、デバッガでトレースしてみたところ
vector<bool> は1要素を1ビットで表現するという特別な処理をしているようには見えませんでした。
ということは VC++6.0 であれば vector<bool> を使っても問題ないと理解してよろしいのでしょうか?
>>871
使うコンパイラに関係なくstd::vector<bool>を使っても問題ないが、
メンバ関数が返す値はboolへのリファレンスでなくてプロキシである
ことを知っておく必要がある。
>>870さんも言っているように、
bool* p = &vecBool[x]; のようなコードがコンパイルできない。
>>870
> ビットにパックされているために bool *p = &vecBool[x]; とかができないとか?
当たり。できません。
んでもって、これができないモノは正確には「コンテナではない」んだそうです。
よって「vector<bool>はSTLコンテナではない」が成り立つとかなんとか。

なんとなく心配なら、deque<bool>を代用品に選んどくのもいいかも。
>>871
例えばVC++6 ProのSP5なら、<vector>の245行目以下で
boolをunsigned intにパックしてるが。
875STL初心者:03/02/27 19:16
>>874
あれっ、ほんとだ。
でも vector<bool> vb; と宣言し vb.push_back(true); を実行しても
class vector<_Bool, _Bool_allocator> が利用されていないように
見えるが・・・
876STL初心者:03/02/27 19:19
それに VC++6.0 で
vector<bool> vb;
vb.push_back(true);
bool *pb = &vb[0];
をコンパイル実行してみると、問題ないようだぜ。
パックするには何かおまじないがいるのかな?
std::vector<bool>で
std::vector<bool, std::allocator<bool> >か、
bool専用のアロケータが使われるかは処理系依存で
さらにbool専用のアロケータの名前も規定されてない
878デフォルトの名無しさん:03/03/01 23:41
VC.netで、boostのコンパイルがうまくできません。
bjamとかって標準のインストールパスにしか対応していないのですか?
最近STL使い始めた初心者です。
グローバルでSTL宣言すると12バイトのメモリリークが起きるようなんですが、
これの解消法ってどうすればいいんですか?
>>879
よーわからんけど、「12バイトのメモリリーク」 はどうやって確かめたの?
881デフォルトの名無しさん:03/03/03 00:01
template <class charT>
const charT *mes()
{
return "message";
}

質問です
mes<char>(); //はOK
mes<wchar_t>(); //だめ、理由はわかってます。でもどうしたらいいのでしょうか
return TEXT("message"); // ←こうかもしれない。
>>881
template <>
const wchart_t *mes()
{
return L"message";
}
>>883
ああ、そりゃそうですね・・・
ども
885879:03/03/03 21:24
>>880
あ、すみません、説明不足でした。

list<int> hoge;
という風にグローバルで宣言して、そのまま終了すると
12バイト漏れる、ということで。

メモリリークを調べるのには
_CrtDumpMemoryLeaks()
を使いました。
グローバルに静的に確保されたオブジェクトにリークもクソもないと思うが。
グローバルで宣言したクラスの
コンストラクタとデストラクタが呼び出されるタイミングと
_CrtDumpMemoryLeaksが呼び出されるタイミングを考えてみろ
VC6だとlocaleでリーク起こすけど
using namespace std;
try{
locale::global(locale("2ch"));
} catch(exception &e) {}
これでリーク起こす。
>>888
VC6はC Runtimeのソース付いてるから直せるぞ
890879:03/03/04 21:01
>>887
あー・・・。
気付きませんでした。どうもです。
891デフォルトの名無しさん:03/03/05 08:35
VC6の出力が \ になるのですが、なぜに?

#include<sstream>
#include<string>
#include<iostream>
#include<vector>
using namespace std;

int main()
{
basic_stringstream<wchar_t> S;

const char c[]="圭";
size_t size = mbstowcs(NULL,c,0);
vector<wchar_t> tmp(size+1);
wstring data;
mbstowcs(const_cast<wchar_t*>( &tmp[0] ),c,size);
*(static_cast<volatile wchar_t*>( &tmp[0] )+size) = L'\0';
S << &tmp[0];
S >> data;
wcout << data;// VC6だと\, VC.NETだと圭
}
まず、setlocaleしる。

> mbstowcs(const_cast<wchar_t*>( &tmp[0] ),c,size);
> *(static_cast<volatile wchar_t*>( &tmp[0] )+size) = L'\0';
ここのキャストは要らないと思うんだけど。
 mbstowcs(&tmp[0],c,size);
 tmp.back() = L'\0';
これでいいはず。

んで、試してみたけど。
 wcout << &tmp[0] << endl;// 「圭」
 wcout << S.str() << endl;// 「圭」
 wcout << data << endl;// なにもでない

> S >> data
こいつがうまくいかないみたい。
原因は追いきれなかった。
893デフォルトの名無しさん:03/03/05 11:29
VC6.0です(STL?)。

Redo/Undoの機能をつけるために
ポインタをポインタの配列で管理しようとしているのですが

配列のサイズを決めて新しい要素を入れると
古いものから順に消していってくれるような都合のいい
クラステンプレートってないですか?
894デフォルトの名無しさん:03/03/05 11:35
>>892

>setlocale(LC_ALL,"Japanese");を忘れてました。

ライブラリ側の問題ぽいので
S.str()で回避して使っていこうと思います。

ありがとうございました。
>>893
std::queueのラッパーでいいんじゃねーの。
キュー、っつーかリングバッファだな。
リングバッファを実現するコンテナアダプタはSTLの解説で幾つか見たことあるが、
公開されてるものはない気がするから自分で作ったほうがはやそう。
897893:03/03/05 12:16
>>895, 896
どっかから参考になりそうなものを探して自作することにします。
ありがとうございました。
FIFOバッファだからdeque使えばいいだけの話じゃないの?
899 :03/03/05 15:38
stlport_vc6.dll を stlport.dll にリネームして使いたいと思います。
方法がわかる方はいらっしゃいませんか?
いらっしゃいましたら、方法を教えてください。

まさか stlport_vc6.lib をバイナリ・エディット?
900デフォルトの名無しさん:03/03/05 17:56
G++でwcoutを使うにはどうすればよいのでしょうか?
901デフォルトの名無しさん:03/03/05 18:21
std::vector<std::string> a;
ってやっちゃだめなの?
>>901
当然良し。
903デフォルトの名無しさん:03/03/05 19:08
vector<bool>を使ったらだめな理由がわかりません。
つーか便利だよ
vector<char>だと8倍メモリくうし

bool *p=&vec[0];
これができないとなんでだめなんだよー
904デフォルトの名無しさん:03/03/05 19:16
905デフォルトの名無しさん:03/03/05 19:23
>>902
vcでレベル4でコンパイルするとめちゃめちゃヲーニングでるけど
なんかあやしいきもするんですが・・・
>vcでレベル4でコンパイルするとめちゃめちゃヲーニングでるけど
VC6発見

#pragma warning (disable : 4786)
ソースの先頭に置いときなさい
>>906
はーい
>>885
ちょいと遅レスだがたしかSTLは効率のために内部にちょびっと
つねにメモリもってるらしいよ。どっかの過去ログにあるはず。
で、どっかで何かをdefineすればなくなるがパフォーマンス
悪くなる。(ってことなのかな?的外れだったらスマソ)
>>908
そういうのはメモリリークとは言わないけどね。
>>908
メモリプールといいます。そういうのは。
911デフォルトの名無しさん:03/03/06 02:33
コンテナとかはstlport使ってるんですが、
stlportのiostreamを使う利点はあるのですか?
static-linkだと容量でかくなるし
もしたいした違いがないならコンパイルせずに
標準のiostream使おうと思うので
教えてください
912デフォルトの名無しさん:03/03/06 12:01
STLportのCVSにWinCVS(or TortoiseCVS)でアクセスできませんか?
913912:03/03/06 12:02
もちろん、読み取りだけで十分です。
>>900
glibc のバージョンが古いと思われ。
glibc-2.2(だったかな?)以降が入ってる環境を使うべし。
915デフォルトの名無しさん:03/03/07 05:41
 set<string> coll;
という変数宣言がされている状況で、
 for_each(istream_iterator<string>(cin), istream_iterator<string>(),
      coll.insert);
としたいんだけど、gcc-2.95.3 では
no matching function for call to `for_each (istream_iterator<string>, istream_iterator<string>, {unknown type})'
とエラーになってしまう…
(本当はもっとエラーメッセージが長いけど、適宜省略)

プロ言C++第3版の13.2.3を見ると「テンプレート引数としては…メンバに対す
る多重定義されていないポインタなどが使える」とあって、これからすると、
このset<string>::insertみたいな多重定義されているメンバ関数はテンプレート
引数としては渡せないような気もするんだけど、これって本当?
916915:03/03/07 05:42
やりたいことは、下記のような関数オブジェクトInserterを作って、
 template<class Collection>class Inserter {
  private:
     Collection *container;
  public:
     Inserter(Collection &c) { container = &c; }

     void operator()(const typename Collection::value_type &v)
     {
         (*container).insert(v);
     }
 };
coll.insert の代わりに Inserter< set<string> >(coll) と書けば
できたけど、なんか納得いかないというか、イマイチGenericじゃない
気がしてる。実際、for_eachを手で展開して
 istream_iterator<string> in(cin);
 while (in != istream_iterator<string>())
     coll.insert(*in++);
とすれば動くだけに、なんかクヤしい。
なんか良い手ないかしら?
std::insert_iterator, std::inserterというのがあるわけだが。
#include <iostream>
#include <set>
#include <string>
#include <iterator>
#include <algorithm>

int main()
{
std::set<std::string> sset;
std::copy(
std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
std::inserter(sset,sset.begin()));

std::copy(sset.begin(),sset.end(),std::ostream_iterator<std::string>(std::cout,"\n"));

return 0;
}
>>916

std::set<std::string> coll;
std::copy(std::istream_iterator<std::string>(std::cin), std::istream_iterator<std::string>(), std::insert_iterator<std::set<std::string> >(coll, coll.begin()));

std::setに関するstd::insert_iterator()の定義はちょっと面白いようになっている。
c.insert(p, t) を呼び出すわけだが、std::setではinsertのメンバ関数は探索位置を
指定する必要はない。だが互換性のためにヒントとしてパラメータを持っている。
そのためstd::insert_iterator()が使えるのである。
std::back_inserter()は使えない。なぜならstd::setはpush_back()というメンバ関数を
持たないからだ。
>>918-920
ども。それは分かります。
ただ、915-916 で言いたかったのは、この処理は間違いなく
for_eachイディオムで書ける筈だし、実際マクロならFOR_EACH
の形で書けので、templateでだって可能じゃないのか、916で
やったように、insertをハードコードすることなく、(Scheme
なら lambda を使って簡単に書けるわけだから) C++ でもなにか
方法がある筈じゃないのかってことなんでした。
もっとも 915-916を書いた時点では、自分でも何が気に入ら
なかったのかはっきりしてなかったので、うまく書けませんでした。
922915:03/03/07 18:59
で、915で書いた推測は全く見当はずれでした。

3点大きな間違いがあって、まずそもそも「coll.insert」
っていうのは、C++ の文法上許されない表現なので、
template関数の引数には書けません。(^^;
正しい表現は &set<string>:insert となりますが、
この場合、&set<string>:insert だけでなく coll も
別に渡してやる必要がありました。

それから、この場合、coll.insert を渡している場所は
テンプレート引数ではなく、テンプレート関数の通常の
引数なので、くだんのプロ言C++第3版の13.2.3の記述は
そもそも関係ありませんでした。

最後に、ちゃんと確認してみたところ、使っている処理系
(gcc-2.95.3)だと、多重定義されているメンバ関数を
テンプレート引数として渡すことだって可能でした。
(gccの拡張機能?)
で、922で書いたようにcollも渡す必要があるわけで、
mem_fun_refに習って、次のような関数オブジェクトを定義しました。

template<typename ReturnType, typename Class, typename Arg1Type>
class obj_mem_fun1_t : public unary_function<Arg1Type, ReturnType> {
private:
    Class *object;
    ReturnType (Class::*memfun)(Arg1Type);
public:
    explicit obj_mem_fun1_t(Class &o, ReturnType (Class::*mf)(Arg1Type))
        : object(&o), memfun(mf) {}

    void operator()(Arg1Type a1)
    {
        ((*object).*memfun)(a1);
    }
};

template <typename ReturnType, typename Class, typename Arg1Type>
inline obj_mem_fun1_t<ReturnType, Class, Arg1Type>
obj_mem_fun(Class &object, ReturnType (Class::*mf)(Arg1Type))
{
    return obj_mem_fun1_t<ReturnType, Class, Arg1Type>(object, mf);
}
924915:03/03/07 19:04
これで、
 for_each(
 istream_iterator<string>(cin),
 istream_iterator<string>(),
   obj_mem_fun(coll, &set<string>::insert));
とすればOKかなと思ったんですが、gcc-2.95.35だと
no matching function for call to `obj_mem_fun (set<string> &, {unknown type})'
となってしまいました…
925915:03/03/07 19:07
しかし、テンプレート引数を明示的に指定して
 for_each(
   istream_iterator<string>(cin),
   istream_iterator<string>(),
   obj_mem_fun<
     pair<set<string>::const_iterator, bool>,
     set<string>,
     const set<string>::value_type &
   >(coll, &set<string>::insert));
とすればコンパイルもでき、動作しました。
これで、915-916で思ってたことは、ほぼ満足です。
(テンプレート引数を明示しなければいけないのが
ちょっと残念だけど。)
926915:03/03/07 19:12
で、またまた疑問なんですが、のコンパイルエラーは
仕様なんでしょうか、バグなんでしょうか、それとも
未定義な部分(実装上の制限)なんでしょうか?

それから、こういう、オブジェクトに対する呼びだし
obj.message(arg1) を普通の関数呼びだし func(arg1)
の形式に変換する関数アダプタって、標準的にあって
も良さそうな気がするんですが、boost とか、そういう
準標準ライブラリとして、こういうものってないんで
しょうか?
927915:03/03/07 19:15
< で、またまた疑問なんですが、のコンパイルエラーは

う、書き間違えました。これは

> で、またまた疑問なんですが、924のコンパイルエラーは

でした。
boostのbindを調べてください
template <typename ReturnType, typename Class, typename Arg1Type,typename Class2>
inline obj_mem_fun1_t<ReturnType, Class, Arg1Type>
obj_mem_fun(Class2 &object, ReturnType (Class::*mf)(Arg1Type))
{
return obj_mem_fun1_t<ReturnType, Class, Arg1Type>(object, mf);
}

こうしたらVC7でとおった
>>926
何がやりたいのかよくわからん
931915:03/03/08 07:05
>>928

ドキュメントを読んで下記を試してみたところ、期待通りに
動作しました。
 for_each(
  istream_iterator<string>(cin),
  istream_iterator<string>(),
  boost::bind< pair<set<string>::const_iterator, bool> >(
   boost::mem_fn(&set<string>::insert), boost::ref(coll), _1));
素晴らしいです。どうもありがとうございました。

最初は下記のやり方を試したんですが、こちらの書き方だと、
自作のもっと単純な型に対しては動くんですが、set<string>
に対しては、924 と同様の症状でコンパイルに失敗してしまいました。
 for_each(
  istream_iterator<string>(cin),
  istream_iterator<string>(),
  boost::bind(&set<string>::insert, boost::ref(coll), _1));
>>931
> boost::bind< pair<set<string>::const_iterator, bool> >(
>   boost::mem_fn(&set<string>::insert), boost::ref(coll), _1));
その使い方だったらboost持ち出すまでもなく
bind1st<...>( mem_fun(&set<string>::insert), &coll )
でよくない?
933915:03/03/08 09:53
>>932
なるほど。言われてみれば確かにその通りです。
mem_funを使って
 for_each(
   istream_iterator<string>(cin),
   istream_iterator<string>(),
   bind1st(
 mem_fun<
   pair<set<string>::const_iterator, bool>,
   set<string>,
   const set<string>::value_type &
 >(&set<string>::insert),
 &coll));
とするか、あるいはmem_fun_refを使って
 for_each(
   istream_iterator<string>(cin),
   istream_iterator<string>(),
   bind1st(
 mem_fun_ref<上に同じ>(&set<string>::insert),
 coll));
とすれば、うまく行く筈ですね… と思ってやってみたら、
例の「参照への参照」問題が発生して、どちらもコンパイル
エラーになってしまいました…

bind1stが定義する関数オブジェクトの呼びだし時に、
set<string>::insert() の引数型(const string への参照です)
への参照型を使って渡そうとするのが、原因のようです…
うーんgcc3.2.2(MinGW)ではコンパイルに失敗するね。
移し間違えているのかな?

std::set<std::string> coll;
std::for_each(
std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
boost::bind<std::pair<std::set<std::string>::const_iterator, bool> >(
boost::mem_fn(&std::set<std::string>::insert), boost::ref(coll), boost::lambda::_1));

C:/MinGW/boost/set_insert.cpp: In function `int main()':

C:/MinGW/boost/set_insert.cpp:19: no matching function for call to `
mem_fn(<unknown type>)'
935915:03/03/08 12:16
あれれ、unknown typeになりますか。mem_fn()のテンプレート引数を
明示的に指定するとどうでしょう?
set<string> coll;
for_each(istream_iterator<string>(cin), istream_iterator<string>(),
  boost::bind< pair<set<string>::const_iterator, bool> >(
    boost::mem_fn<
      pair<set<string>::const_iterator, bool>,
      set<string>,
      const set<string>::value_type &
    >(&set<string>::insert), boost::ref(coll), _1));
手元の環境だと、この場合、bind()の方のテンプレート引数は
省略可能になります。
>>935
さらに強烈なエラーが出てきました。

C:/mingw/include/boost/bind.hpp: In member function `R boost::_bi::list2<A1,
A2>::operator()(boost::_bi::type<R>, F, A&) const [with R =

std::pair<std::_Rb_tree_iterator<std::string, const std::string&, const
std::string*>, bool>, F =
boost::_mfi::mf1<std::pair<std::_Rb_tree_iterator<std::string, const
std::string&, const std::string*>, bool>, std::set<std::string,
std::less<std::string>, std::allocator<std::string> >, const std::string&>,
A = boost::_bi::list1<const std::basic_string<char, std::char_traits<char>,
std::allocator<char> >&>, A1 =
boost::reference_wrapper<std::set<std::string, std::less<std::string>,
std::allocator<std::string> > >, A2 =
boost::_bi::value<boost::lambda::lambda_functor<boost::lambda::placeholder<1>
> >]':
C:/mingw/include/boost/bind/bind_template.hpp:33:
instantiated from `boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()(A1&)
[with A1 = const std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
R = std::pair<std::_Rb_tree_iterator<std::string, const std::string&, const std::string*>, bool>,
F = boost::_mfi::mf1<std::pair<std::_Rb_tree_iterator<std::string, const std::string&, const std::string*>, bool>,
std::set<std::string, std::less<std::string>, std::allocator<std::string> >, const std::string&>,
L = boost::_bi::list2<boost::reference_wrapper<std::set<std::string, std::less<std::string>, std::allocator<std::string> > >,
boost::_bi::value<boost::lambda::lambda_functor<boost::lambda::placeholder<1> > > >]'
C:/mingw/include/c++/3.2.2/bits/stl_algo.h:157:
instantiated from `_Function std::for_each(_InputIter, _InputIter, _Function)
[with _InputIter = std::istream_iterator<std::string, char, std::char_traits<char>, ptrdiff_t>,
_Function = boost::_bi::bind_t<std::pair<std::_Rb_tree_iterator<std::string, const std::string&, const std::string*>, bool>,
boost::_mfi::mf1<std::pair<std::_Rb_tree_iterator<std::string, const std::string&, const std::string*>, bool>,
std::set<std::string, std::less<std::string>, std::allocator<std::string> >, const std::string&>,
boost::_bi::list2<boost::reference_wrapper<std::set<std::string, std::less<std::string>,
std::allocator<std::string> > >, boost::_bi::value<boost::lambda::lambda_functor<boost::lambda::placeholder<1> > > > >]'
C:/MinGW/boost/set_insert.cpp:23: instantiated from here
C:/mingw/include/boost/bind.hpp:233: no match for call to `(
boost::_mfi::mf1<std::pair<std::_Rb_tree_iterator<std::string, const
std::string&, const std::string*>, bool>, std::set<std::string,
std::less<std::string>, std::allocator<std::string> >, const std::string&>)
(std::set<std::string, std::less<std::string>, std::allocator<std::string>
>&, const boost::lambda::lambda_functor<boost::lambda::placeholder<1> >&)'
C:/mingw/include/boost/bind/mem_fn_template.hpp:129: candidates are: R
boost::_mfi::mf1<R, T, A1>::operator()(T*, A1) const [with R =
std::pair<std::_Rb_tree_iterator<std::string, const std::string&, const
std::string*>, bool>, T = std::set<std::string, std::less<std::string>,
std::allocator<std::string> >, A1 = const std::string&]
C:/mingw/include/boost/bind/mem_fn_template.hpp:134: R

boost::_mfi::mf1<R, T, A1>::operator()(U&, A1) const [with U =
std::set<std::string, std::less<std::string>, std::allocator<std::string> >,
R = std::pair<std::_Rb_tree_iterator<std::string, const std::string&, const
std::string*>, bool>, T = std::set<std::string, std::less<std::string>,
std::allocator<std::string> >, A1 = const std::string&]

C:/mingw/include/boost/bind/mem_fn_template.hpp:139: R
boost::_mfi::mf1<R, T, A1>::operator()(T&, A1) const [with R =
std::pair<std::_Rb_tree_iterator<std::string, const std::string&, const
std::string*>, bool>, T = std::set<std::string, std::less<std::string>,
std::allocator<std::string> >, A1 = const std::string&]

Execution terminated
939デフォルトの名無しさん:03/03/08 22:05
string文字列中の特定の文字Aを検索し、
その文字以降Bが出現するまでの文字列を抜き出したい場合
どうすればよいですか。

string str(`hoge...`);
string::iterator sp;
string::iterator ep;

sp = find(str.begin(), str.end(), 'A');
ep = find(sp, str.end(), 'B');

で要素位置はわかりますが、これをどう使えば
要素を抜き出せるのか。。。
string str("fawAejkreBf");
string::size_type pos=str.find_first_of('A');
if(pos!=string::npos)
{
pos++;
str=str.substr(pos,str.find_first_of('B',pos)-pos);
}
>>939
string AtoB(sp, ep);
>>936
エラーは no match for call to ですか…
なんかメソッドの signature が違っているくさいですね。
コンパイラというよりは、STL の実装の違いのような気が
するんですが、UNIX系OS上の gcc-3.2.1 では 935で問題
なく通りました。gcc-3.2.1と3.2.2で、STL回りって、
そんなに変わっているんでしょうか。
>>942
原因がわかりました。_1 はてっきり boost::lambda::_1 かと思ってたの
ですが、boost::bind の _1 だったのですね。
無事通りました。ありがとうございます。
gcc3.2.2でも通りました(当たり前ですよね)。

ただ、やはり boost:mem_fn のテンプレート引数を明示的に指定しないと
コンパイル通りません。
>>940
>>941
さま。
ありがとうございます。
945デフォルトの名無しさん:03/03/11 12:20
std::ofstream ofs("test.bin",std::ios::binary);
int tmp = 12;
ofs << tmp;

こうしても、バイナリ出力にはなりませんよね。
fstream系でバイナリ入出力って無理なんですか?



もひとつ。

template<typename T>
void Hoge(const T& t){ /* 省略 */}

に対して、Tが vector<T> みたいなものだった場合は
別なことをさせたいんですが、特殊化でしょうか。
あくまでvector<T>です。まだ型は完全に
決まってないので、部分特殊化なんでしょうか?
VC6で、どうやればいいんでしょうか……?
>>945
バイナリイメージの出入力なら、std::ios::binary付けたうえで、
reinterpret_cast&read/writeかな。

VC6でふつうに部分特殊化したらエラーになった。
サポートできてないんだっけ?
>>945
部分特殊化というよりは、template関数のpartial ordering。
確かVC6では使えないので、何かトリックを使って頑張るしか無いのでは。
948デフォルトの名無しさん:03/03/13 17:40
微妙にスレ違いですが、質問お願いします。

stringから、整数や実数に直接入力する方法ってありますでしょうか。
今は下記のようにやっています。
string str = "777";
int c = atoi(str.c_str());

なんていうかstdlib.hをインクルードするのが悔しいというか・・・アホですいません。
ストリームみたいに、stream >> intみたいな感じで可能ならなぁ、と。

949ヽ(´ー`)ノ:03/03/13 18:00
>>948
boost::lexical_cast 使え…とかそういう話?
950ヽ(´ー`)ノ:03/03/13 18:03
ミスって投稿しちゃった。こんな感じ。

#include <string>
#include <boost/lexical_cast.hpp>

int main(int argc, char **argv) {
string str = "777";
int c = boost::lexical_cast<int>(str);

return 0;
}
951948:03/03/13 18:09
>>950
すごい!

            ・・・・boostってすごい_| ̄|○


λ...........オトシテコヨウ…


と、レスありがとうございました。すいません、環境書かなくて…。
今は腐ったVC++6付属の使ってますが、これを機に移行してみようと思います。
>>951
boost::lexical_castは内部的にstd::stringstreamを使っている。
バラして書けばこんな感じ。簡単だろ。

int main()
{
std::string str("123");
std::stringstream sstr(str);
int i;

sstr >> i;

std::cout << i << std::endl;
}
953948:03/03/13 19:16
>>952
す、素敵すぎです!ありがとうございました。
移行はするとしても、当座はこれでしのいでみます。
>>953
ちなみにstd::stringstreamのコンストラクタを起動した直後は書き込み位置
も読み込み位置もゼロになっているようだから、適当にシークして追加する
と良い。本当はstd::ios::pos_typeをstd::coutに出力できない場合もあるんだ
けどね。あくまでも例って事で。

int main()
{
std::string str("123");
std::stringstream sstr(str);
int i, j;
std::ios::pos_type p;

p = sstr.tellg();
std::cout << "read pos = " << p << std::endl;
p = sstr.tellp();
std::cout << "write pos = " << p << std::endl;

sstr.seekp(0, std::ios::end);

sstr << " 456";
sstr.seekg(0, std::ios::beg);
sstr >> i >> j;

std::cout << i << ' ' << j << std::endl;
}
sstr.seekg(0, std::ios::beg);
はいらなかったかな。
C++のストリームはCとは違って読み込みと書き込みのポインタは
別々だからね。
956948:03/03/13 22:02
>>954-955
いやはや、コードは言葉より雄弁と言いますか・・・。
分かりやすくて本当にためになりました。ありがとうございました。

読んで置いて良かった・・・正直いうと、こんな使いかたしてましたよ(笑

int main()
{
int i;
std::string str("123");
std::stringstream( str ) >> i;

std::cout << i << std::endl;
}
>>945

#include <vector>

template<typename T>
struct foo {
static void Hoge(const T& t)
{
*****
}
static void Hoge(const std::vector<T>& t)
{
****
}
};

foo<int>::Hoge(0);
foo<int>::Hoge(std::vector<int>());

とかじゃダメなの?
958957:03/03/14 00:17
>>945

やっぱ上のじゃ不便だな、ってことで以下...

template <int N> struct foo {
template <class T> static void baka(const T& t) { //hogehoge }
};

template <> struct foo<1> {
template <class T> static void baka(const std::vector<T>& t) { //hogehoge }
};

template <class T> char hage(const std::vector<T>& t);
double hage(...);

template<typename T>
static void Hoge(const T& t) { foo<sizeof(hage(t))>::baka(t); }

void test() {
int a = 3;
std::vector<int> v(8);
Hoge(a);
Hoge(v);
}

ちゃんとディスパッチできたよ。
sizeof(char) < sizeof(double) だと規格のどこに書いてあるのか小一時間(略
>>956
うぉ、こんなやり方でもできるんだな
やっぱ使うのまずいっぽ?

コンストラクタで作ってから、どうなってるんだろ
デバッガで追ってみたけどテンプレートが複雑でいまいちわからん
960デフォルトの名無しさん:03/03/15 03:43
>>945
ふつうにオーバーロードで
template<typename T>
void Fn(const T&){}

template<typename T>
void Fn(const std::vector<T>&){}

int main(){
Fn(int() );
Fn<int>(std::vector<int>() );//Fn<int> 明示的に型指定
return 0;
}

>>956
の示したコードの使い方、あれでいいんじゃないですか?
あってるよね?
962958:03/03/15 10:20
>>960

なるほど<int>と限定した上ではただのオーバーロードに
なるんだね。
複雑にして損したよ
963956:03/03/15 21:32
>>959 >>961
自分で書いて置いてなんですが、あってるんですか?
さすがに無理な気がしないでもないです…要するにこういう事ですよね?

#include <iostream>

class B{
public:
void hage(){
std::cout << "Hoge" << std::endl;
}
};

int main(){
B().hage();

return 0;
}

実体はどこに・・・というかうちのコンパイラ(VC++6.0)以外でも通るのだろうか。
詳しい方のご意見をお尋ねしたいところです。ってC++スレの方がいいのかな。
>>963

ん?一時オブジェクトの寿命の問題でしょ
全然問題ないよ
965956:03/03/15 22:00
>>964
いやぁ、そうなんですか・・・また一つ勉強になりました。

てっきり、Bコンストラクタのスコープから出た瞬間、
デストラクタが呼ばれるのかと思ってました。
Bコンストラクタ>hage>Bデストラクタは保証されているんですねぇ。

うーん、ダメだ。自分この辺ぐだぐだで・・・再勉強してきます。
レスありがとうございました。
一時オブジェクトってのは非constな参照では受けられないけど
非constなメソッドを呼べるという特殊な存在。
この性質を利用したテクニックもある。
でもこれを多用すると一部の論者に睨まれるという諸刃の剣。
一時オブジェクトって、非constな参照で受けられなかったんだ……。
言われてみると、敢えて受けてみたことはないな。
thx.

>>966
おまけに自分自身を返すメソッドを呼ぶと
非constな参照で受けることが可能になるだけでなく
当然左辺値として扱うことも可能になる。

一時オブジェクトは非constな参照で受けることが
できない/右辺値として扱われるって
仕様はホントにあほらしいんだよなぁ。
そんなんだったら始めからエラーじゃなくて、
ワーニング程度に留めとけっての。
>>960

intと明示的に型指定できるくらいだったらvectorなのか
そうでないのかもわかるだろうから、オーバーロードすら
必要ないんじゃない?
970デフォルトの名無しさん:03/03/16 16:46
>>969

>>945
を、よめ!!!!!!!!!

ちなみにほかのコンパイラーなら
明示的の指定はいらん
971デフォルトの名無しさん:03/03/16 16:49
>>963
そういう使い方ならstatic関数にすればいいやん
B::hage(); みたいに
>>970

945の意味するところが『いずれテンパラはある一つの型に決めます』ってなら
<T>の部分を明示するのは抵抗ないだろうけどね。
テンパラになる型が最終的に複数出てくる場合はどうだろう。
と思って957→958という流れになったわけだが
973デフォルトの名無しさん:03/03/16 17:25
staticにしたらこんなのが通らん

#include<cstdio>

//#define STATIC__
struct FuncOperator
{
#ifdef STATIC__
static void operator () (){ puts("static operator"); }
#else
void operator () (){ puts("Non static operator"); }
#endif
};

int main(){

#ifdef STATIC__

FuncOperator::operator ()();
#else
FuncOperator()();

#endif

return 0;
}
staticなオペレータって蟻なのか?
>>974

為し
976945:03/03/17 13:24
>>958さん、ありがとうございます。たしかにうまくいきますね。
で、えぇと……実はHoge()はあるクラスのメンバ関数なんですが、
この場合はどうしたらいいんでしょう?^^;

条件が後出しになって申し訳ありません。詳しく状況を言いますね。
まず、バイナリの入出力を簡便にしてくれるクラスが欲しいのです。
標準だと、こうなりますよね。

ifstream ifs("piyo.dat",ios::binary);
int n;
ifs.read(reinterpret_cast<char*>(&n),sizeof(int));
vector<int> v(n);
ifs.read(reinterpret_cast<char*>(&v[0]),sizeof(int)*n);

これだとあまりにも面倒なのです。不要な指定が多すぎて。

CReadFile rf("piyo.dat");
int n;
rf >> n;
vector<int> v(n);
rf >> v

こういう感じですっきり指定できるラッパークラスを作りたいのです。
出力の方も、同じ要領でやりたいと思ってます。
これで、intだけを入出力したいわけじゃないから、templateで、
ということなんです。
で、VC6固有の(ですよね?)templateヘタレ解析に悩まされてるわけです。
そういうわけですので、>>960さんみたいなやり方は、クラス使用者の
負担になりますので、あんまり意味がないわけです。
>>958さんのやり方みたく、多少機種依存の部分があっても、なんとか
隠蔽できればいいんですけど……。
して、次スレの方は?
>>976
template <class T> void hoge(const T &);
を用意しなければいいのでは

つまり
void hoge(int);//unsigned int,float,なども用意する
template <class T> void hoge(const vector<T> &);

でどうでしょう? あんまり無条件でバイナリ保存できる型なんてそうそうないでしょ?
逆に安全性の面から用意されていないと入出力できないようにしたほうが良いとおもわれ
979デフォルトの名無しさん:03/03/17 17:42
reinterpret_cast<?>(?)のなにがいやぁーなの
もしながくていやとかぬかしてんのそれなら(char*)キャスト使えば
もし、それでもかっこ悪いとか言うんなら自分でvector<T>専用をつくれば

template<typename T>char* Cast(std::vector<T>& tt)
{return reinterpret_cast<char*>(&tt[0]); }

こんな感じに。
さらにintとunsigned charを使い分けたいなんて我侭もあるんなら

union bit{
int i;
unsigned char bitn[4];
};
std::vector<bit>これで読み込ませればint、
unsigned charの使い分けが一回の作業で実現できよう。
とにかくreinterpret_castぐらいでクラスなんて作ってられない


#define scast static_cast
#define rcast reinterpret_cast
#define ccast const_cast
#define dcast dynamic_cast
template <class T,class U> T scast(const U &u)
{ return static_cast<T>(u); }
982デフォルトの名無しさん:03/03/17 21:14
>>980
それをやるならここでは、こうでしょ。。
#define Cast(M) reinterpret_cast<char*>(M)
983デフォルトの名無しさん:03/03/17 21:19
>>981
いみない。結局明示的に指定しなくちゃならんでしょ
>>982
char * 型以外に使えないじゃん。
ねえ、早く!
987スレタイはこれで:03/03/18 02:09
template<typename STL,Boost,Loki,etc>class part2
>>987
<> は化けるのでは?
一応新スレ立てときました。

【C++】template 統合スレ -- Part2
http://pc2.2ch.net/test/read.cgi/tech/1047978546/
990 :03/03/19 06:35
〈〉←これで代用という手がある。
991デフォルトの名無しさん:03/03/19 20:53
777?
992デフォルトの名無しさん:03/03/19 22:52
この板では1000ゲットは興味なしですか?
ぬるぽがこのスレに興味を持ったようです。

  ∧_∧
 ( ´∀`)< ぬるぽ
  ∧_∧
 ( ´∀`)< ぼくぬるぽ
もうすぐか…
なにが?
>>996
1000が
 
999
そんなバカなやり取りしてる間に1000げt
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。