トップページ⇒tech
1001コメント388KB

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

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさんNGNG
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 あたりに。
0013デフォルトの名無しさんNGNG
>>12
std::auto_ptrが継承に対応してないからかと思ったけど、どうも区別が
曖昧だというエラーが出るね。
0014○NGNG
なかなか難しいよね。templateベースのものは。
まあ仕事にも使った事はあったけど。便利なんだけど。
0015デフォルトの名無しさんNGNG
継承は対応してないのか。確かに通らんね。

#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);
}
0016デフォルトの名無しさんNGNG
auto_ptr<B>とauto_ptr<D>は単に別の型であって、
暗黙の型変換ができなかった、ということでは?

>>15
そこでdynamic_castを思い浮かべてしまうというのは
ちと知識不足すぎやしませんか。ネタ?
0017デフォルトの名無しさんNGNG
>>16
いや(汗、本当に継承に対応してないのかと思って。
でもパラメタの型が違うから当たり前か・・・・
001812NGNG
>>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の最初のコードが
コンパイルできるように配慮されているように見えます。

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

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

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

モッカイageテミル
0028デフォルトの名無しさんNGNG
>>25
release()必要ないのでは?std::auto_ptrのコンストラクタは所有権を
移動させるから。
0029デフォルトの名無しさんNGNG
auto_ptr<T>とauto_ptr<U>の互換性があるかどうか分からないのに、
どうやって所有権を移動させるんだ?
0030デフォルトの名無しさんNGNG
継承と同じように考えて、親クラスのポインタ変数に子のオブジェクトのアドレス
を代入できるかと自然と考えてしまいました。でもstd::auto_ptrは継承とか考慮
してないので、エラーになるのですね。
0031デフォルトの名無しさんNGNG
>>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できるだろ?
003231NGNG
あぁ >>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());}
0033デフォルトの名無しさんNGNG
http://www.zdnet.co.jp/enterprise/0211/11/n20.html
003412NGNG
>>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>();
↑キャストなんて標準で装備されてるこれらで十分のはずだ。
003531NGNG
>>34
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
class B {};
class D {} public B {};
//class D {};
auto_ptr<B> b;
auto_ptr<D> d;
b = cast(d, b);
DがBを継承してなかったらどうなるか。

>キャストなんて標準で装備されてるこれらで十分のはずだ。
あ、そ。で、>>31 の内容は理解できましたか?
0036デフォルトの名無しさんNGNG
2!
0037デフォルトの名無しさんNGNG
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
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 の内容は理解できましたか?
0038デフォルトの名無しさんNGNG
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
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 の内容は理解できましたか?
 え
0039デフォルトの名無しさんNGNG
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
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 の内容は理解できましたか?
  
0040デフォルトの名無しさんNGNG
>そのテンプレート関数はどうやって呼び出すんだ?
質問ですか?説明しなきゃいけないようなこと?
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 の内容は理解できましたか?
       
0041デフォルトの名無しさんNGNG
>>31
通常時、TとUには互換性があるかも知れないが、
auto_ptr<T>とauto_ptr<U>に互換性があるときはT==Uの時だけだろ。
0042デフォルトの名無しさんNGNG
一体このスレは何が起きているんだ?
0043デフォルトの名無しさんNGNG
>>42
もう後には引き下がれない意地と意地のぶつかり合いが
繰り広げられています。
0044デフォルトの名無しさんNGNG
異常なほど向きになっておりますな。
しかも会話がかみ合っていないときている。
0045デフォルトの名無しさんNGNG
意見が噛み合ってないのは議論じゃなくて論破しようとしてるせい。
0046デフォルトの名無しさんNGNG
ん?
とりあえず、前の発言者のレスを引用して、(゚Д゚)ハァ? とか書けばいいわけか?
004712NGNG
>>31
器用な人ですな。

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

(゚Д゚)ハァ?
0049デフォルトの名無しさんNGNG
> > ん?
> > とりあえず、前の発言者のレスを引用して、(゚Д゚)ハァ? とか書けばいいわけか?
>
> (゚Д゚)ハァ?

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

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

>>41
> auto_ptr<T>とauto_ptr<U>に互換性があるときはT==Uの時だけだろ。
いや。 >>18 とか >>34 にも書いてある。
それを、互換性がある、と言わないとか、
class B {}; class D : public B {}; のときは B == D というなら
そういうもんなのねとあきらめる。
005331NGNG
>>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);
}

でどうよ。
0054デフォルトの名無しさんNGNG
これは通るけどこれでもいいの?

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));
}
0055デフォルトの名無しさんNGNG
>>54
その関数実際に呼んでみた?
0056デフォルトの名無しさんNGNG
>>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;
}
0057デフォルトの名無しさんNGNG
で、

pa = cast<A>(ptr);

は通るんですが、

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

はだめなんです。もっとも、この行はrelease()を使った版でも
通りませんでした。
0058デフォルトの名無しさんNGNG
>>56-57
何、通るの!?

げ、STLportだと通るよ。

> ダウンキャストはだめ?
reinterpret_castしてるわけじゃなくて
pointerのoperator=だからねぇ。
0059デフォルトの名無しさんNGNG
>>58
gcc3.2でも通るよ。

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

あっそうですね。考えてみればそうだ。
0060デフォルトの名無しさんNGNG
>>12 の話に戻るけどさ、

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

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

ところで
std::auto_ptr<B> p = std::auto_ptr<B>(std::auto_ptr<D>());
は通るよ。
0063デフォルトの名無しさんNGNG
んー、ということは、std::auto_ptrの代入演算子とコピーコンストラクタの
書き方に対称性がないということになるね。
006460NGNG
あとね
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になっちゃうからいいんだけど。
0065デフォルトの名無しさんNGNG
>>64
それは、std::auto_ptrのコンストラクタがexplicit宣言されている事と
関係があると思う。
0066デフォルトの名無しさんNGNG
つまり、

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

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

auto_ptr<B> b1 = d; // NG

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

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

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

だから明示的にコピーコンストラクタを呼び出してやればいいと思う。
0068デフォルトの名無しさんNGNG
最初の

#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>に変換する変換演算子
を呼び出すか曖昧だからエラーが出たようだ。
0069デフォルトの名無しさんNGNG
そうすると、
return std::auto_ptr<B>(p);は、コピーコンストラクタなのか、それとも
変換演算子なのか?誰か教えてください。
0070デフォルトの名無しさんNGNG
さらに深く調べると、
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));
}

のように書かなければいけないようだ。この場合コンパイル出力をアセンブリ出力
で見てみると、コピーコンストラクタを呼び出した後変換演算子が呼び出されていた。
007160NGNG
>>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の最後の方の段落で説明されているようだ。
0072デフォルトの名無しさんNGNG
>>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;
}
0073デフォルトの名無しさんNGNG
関数も付け加えてみました。スレ違いにてここまで。

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

何度も出てる質問だと思うけど、boost仕事で使ってる?
オレんところは小さい会社だし、仕事がR&D的だし、
わがままは通るから勝手に使っちゃってるけど。
templateやSTLでさえも使えない会社って多いんでしょ?
(ならC++なんか使うなって感じだけどな。)
0083デフォルトの名無しさんNGNG
ここのスレの人はgcc使ってるの?
環境がwindowsだとmingw?
0084デフォルトの名無しさんNGNG
>>83
ワシはBCB6れす。boost::lambda使いたいよ〜。
cygwin-bccはまだ2.95だよね?
0085デフォルトの名無しさんNGNG
オレは g++ 3.2 を使って開発してから vc++ に移植、ってパターンが
多いかな。もちろん boost のスマートポインタが無いと仕事になりません。
次期vc++は、boost も loki もちゃんと通るらしい(というか、コンパイル済み
オブジェクトが添付されるらしい)ので楽しみ。↓参照。
http://www.zdnet.co.jp/enterprise/0211/11/n20.html
0086デフォルトの名無しさんNGNG
SDKのコンパイラも新しくなるのかな?
0087デフォルトの名無しさんNGNG
51>>
C++のテンプレートそっくりなものをそのまま使えるわけでは無いようですが、これによりJavaの型キャストの問題に悩まされなくなり、instanceof修飾子を使わずに済むようになり、よりオブジェクト指向的なコードがかけるようです。
0088デフォルトの名無しさんNGNG
>>85
g++使って書いたコードって、VCでコンパイル通る?
俺はだめだ。template周りが弱すぎるよ、VCって。
そんなわけでVCはほとんど使えない。辛うじてBCBかな。
0089デフォルトの名無しさんNGNG
>>85
コンパイル済みオブジェクトが添付されるって、
exportがサポートされるってこと?それはすごい!!!
0090デフォルトの名無しさんNGNG
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
でいってたすたちっくに配列の初期化するのってこんなんだろか
0091デフォルトの名無しさんNGNG
>>88
さすがに export は無理じゃろ。
たんにregexとかのライブラリがコンパイル済みで提供される、
ってことだと思う。
0092デフォルトの名無しさんNGNG
>>91
Lambdaが使えるなら、それでもいいかも。
0093デフォルトの名無しさんNGNG
>>91
いや、そうでもないんじゃない?
C# にジェネリクス実装するのなら、結局 C++ の export 相当の機構が必要になる。
MS 内部でどういう開発グループ分けになってるかは知らないけど、
彼らが知識共有していくとしたら…。
0094デフォルトの名無しさんNGNG
>>93
C#じゃなくてVC++でしょ(8.0だっけ?)
標準に98%準拠っていうあれでしょ。

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

というか 98% の残りの 2% はいったい何なんだ。
0096デフォルトの名無しさんNGNG
98っていう数字がなんだか微妙だよね(藁
0097デフォルトの名無しさんNGNG
>>93
C#とJavaのGenericsは基底クラスがあるからなぁ。
C++でうまくいくのかなあ。
残り2%がtemplate周りだったらいやだなぁ。
うまくいくならVC8買っちゃうんだけど。
0098デフォルトの名無しさんNGNG
ttp://pc3.2ch.net/test/read.cgi/tech/1033830935/ の322が
何か言ってるんだが、誰か心当たりは?
0099デフォルトの名無しさんNGNG
2ちゃん内に対するリンクを切るのは止めてくれ。
0100デフォルトの名無しさんNGNG
export とベースクラス Object/object がある事って関係ないんじゃ?
0101デフォルトの名無しさんNGNG
>>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は相当楽になるわけで。
0102デフォルトの名無しさんNGNG
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 ?
であってますでしょうか?
0103デフォルトの名無しさんNGNG
>>102
位置指定が正しい場合にのみ、定数時間で挿入ができるらしい。
ttp://www.sgi.com/tech/stl/UniqueSortedAssociativeContainer.html

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

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


0105デフォルトの名無しさんNGNG
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;
}
0106105NGNG
修正:
× struct Type_of<class_id(char)>{typedef int type;};
○ struct Type_of<class_id(char)>{typedef char type;};
0107>>105NGNG
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
0108107NGNG
#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を待つべきかと。
0109107NGNG
今思いついた。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) );
0110105NGNG
>>107
すごすぎる!!!
id_counterってほんとにその名の通りですね。
少し手を加えて
type_ofとtestプログラム作ってみたけど、
こういうものはウプしてもいいのかな?(どういう場所がいいのか)
どうにか手を入れれば、GCCでも動かせそうな気がするんだけど、
自分では無理そうでした。
0111デフォルトの名無しさんNGNG
>>107
逆に、IDから元の型を取得することはできないの?

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

キャストに使えたりするとうれしい。
0112デフォルトの名無しさんNGNG
よく使う foo とか bar とかって、RFC で定義されてたんだな。
知らなかった。
http://www.puni.net/~mimori/rfc/rfc3092.txt
■ このスレッドは過去ログ倉庫に格納されています