【C++】template 統合 ..
[2ch|▼Menu]
511:デフォルトの名無しさん
05/05/15 22:32:53
ん?これでできてるっぽいぞ。
template<> A::A( int b);

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

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

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

515:デフォルトの名無しさん
05/05/15 23:41:17
特殊化とインスタンス化とを混同してない?

516:デフォルトの名無しさん
05/05/15 23:55:33
>508が示したように、コンストラクタテンプレートに対して
テンプレート引数を明示する方法は無い。
しかし、(メンバ)関数テンプレートの特殊化を宣言する再には、
テンプレート引数を明示しなくても、関数引数の型から
テンプレート引数の推測が働く。

>>514
明示的特殊化の構文は
 template<> delcaration
だから、>511は構文的に正しいと言える。

517:デフォルトの名無しさん
05/05/15 23:58:48
構文的には確かに正しいのだけれど、もともとの506の要求は
明示的インスタンス化(≠明示的特殊化)なわけで・・・

518:デフォルトの名無しさん
05/05/16 00:02:05
勉強になった。

519:デフォルトの名無しさん
05/05/16 00:08:01
>>517
それがどうした?
明示的インスタンス化の構文は
 template declaration
だ。あとは同じ。

520:デフォルトの名無しさん
05/05/16 00:12:53
>>519
すまんすまん。それでVC++7.1で通ったよ。

521:デフォルトの名無しさん
05/05/16 00:15:29
コンパイラに「これこれのテンプレートをT型でインスタンス化しますた」
とレポートするスイッチがあればいいのに

522:デフォルトの名無しさん
05/05/16 00:17:31
実体化の位置を決定するルールは結構複雑だからな。

523:デフォルトの名無しさん
05/05/16 00:59:29
おまえらの必死さに笑った。
C++の中途半端なtemplate機能でメンテ不能の駄作を量産してる様は、
まるでVBで汎用ライブラリを作る馬鹿とそっくりだな。

524:デフォルトの名無しさん
05/05/16 01:03:16
C++知らないのに、知ってる振りして
がんばって煽るアンタもそうとう必死だが

525:デフォルトの名無しさん
05/05/16 01:35:46
むしろC++で駄目なのは
テンプレートじゃなくてコンストラクタ

526:デフォルトの名無しさん
05/05/16 01:47:19
>>525
コンストラクタの何が不満だって?

527:デフォルトの名無しさん
05/05/16 02:48:50
純粋なOO言語と比べると
C++のOOは不完全


528:デフォルトの名無しさん
05/05/16 03:05:21
>>526

class A
{
int a;
public:
A( int a_ ) : a(a_){;}
};

class B : A
{
public:
B(){ int a = 略; A::A(a);}
B( int a ) : B(){;}
};

529:デフォルトの名無しさん
05/05/16 03:16:11
何がしたいのか理解に苦しむ。C++について理解しているとは思えないコードだ。

530:デフォルトの名無しさん
05/05/16 03:30:52
>>529
これが出来ないから嫌だなと。

>B(){ int a = 略; A::A(a);}
これはAに突っ込む引数aを
Bのコンストラクタ内で生成したい時。
C++ではAのコンストラクタは、Bの初期化リストにしか
置けないので複雑なロジックは難しい。

>B( int a ) : B(){;}
これは多重定義したコンストラクタから
デフォのコンストラクタを予呼びたい時。
デフォのコンストラクタに生成時にかならず呼ばれる
初期化コードを収める。
これが出来ないと全てのコンストラクタに
同じ初期化コードを書かなければならない。

531:デフォルトの名無しさん
05/05/16 04:43:03
>>530
最初の:AはBの基底クラス。最初にAが構築されなきゃBが構築できない。

2番目の:B() {Init();} B(int a) {Init();hogehoge(a);}

532:デフォルトの名無しさん
05/05/16 08:55:21
最初のは
static int hoge() {return 略}
B() : A(hoge()) {}
とかすれば。


533:デフォルトの名無しさん
05/05/16 09:05:50
>>530
そういうことか。
ではどうしたらいいと思う?
Dは両方いけるんだっけか?

534:デフォルトの名無しさん
05/05/16 09:06:24
>>531
> Aが構築されなきゃBが構築できない
関係ない。

> Init()
Init() の中に初期化リストが書けない。

535:デフォルトの名無しさん
05/05/16 09:07:23
>>532
hoge() の値を初期化リストで2度使いたくなったらやっぱり困るな。
「略」が軽くて副作用がなければ、2回呼び出すんだろうけど。

536:デフォルトの名無しさん
05/05/16 09:10:37
要は設計が悪いんだろ。

537:デフォルトの名無しさん
05/05/16 09:18:31
まあそうだな。C++の設計の悪さは今更いかんともしがたい部分がある。



538:デフォルトの名無しさん
05/05/16 11:19:33
>>530
> C++ではAのコンストラクタは、Bの初期化リストにしか
> 置けないので複雑なロジックは難しい。

コンストラクタの途中でexceptionが起きたことを考えると、
>>532のような方法で初期化リストを旨く使う方法に頭を悩ませるのが良い。
>>528のやり方ではコンストラクト失敗時のデストラクトの扱いがかなり難しくなる。

初期化リストで上手くできない場合は、
exception safeの事を考えるとコンストラクタ自体がかなり複雑になってしまう。

539:>>538
05/05/16 11:21:07
定義順じゃなくて、初期化リスト記述順だといいのになあと思ったことはある。


540:デフォルトの名無しさん
05/05/16 12:06:24
>>539
それだと、コンストラクタごとに初期化順が変わってしまう。
Ex.
class foo {
public:
foo() : a_(), b_() {}
foo(int a) : b_(a), a_(a) {}
...;
};

541:デフォルトの名無しさん
05/05/16 12:21:40
>>540
539はまさにそれを意図しているのだと思うが、何か不都合があるの?


542:デフォルトの名無しさん
05/05/16 12:53:52
>>541
初期化リストに載ってないメンバはどうすればいい? by コンパイラ

543:デフォルトの名無しさん
05/05/16 13:14:10
くるしゅうない。よきにはからえ。


544:デフォルトの名無しさん
05/05/16 13:17:59
構築した順番の逆順で解体することを保証しなきゃならんので
コンストラクタごとに初期化順が変わったら大変だ。

545:デフォルトの名無しさん
05/05/16 14:05:33
なるほど。それもそうだ。



546:デフォルトの名無しさん
05/05/16 15:32:47
つーか藻前らEffectiveC++くらい読んどけよ。

547:デフォルトの名無しさん
05/05/16 20:25:46
template< uint n > class X
{
public:
void f(...);
}

こういうクラスがあったとして、

nが1だった場合 → X::f( uint f0 );
nが2だった場合 → X::f( uint f0, uint f1 );
nが3だった場合 → X::f( uint f0, uint f1, uint f2 );

こういうふうにテンプレート引数によって
関数の引数の数が変わるようにしたいんですが可能ですか?
出来ないまでも、代替手段みたいなのはありますか?

548:デフォルトの名無しさん
05/05/16 20:53:37
あの〜
templateって実はマクロ?

549:デフォルトの名無しさん
05/05/16 21:23:34
>>547
関数のデフォルト引数でなんとかしろ。同一のテンプレートパラメータの型を
持つクラスは2回以上は定義できん。

550:デフォルトの名無しさん
05/05/16 21:58:37
>>549
了解、こういうのも出来るといいですね。

551:デフォルトの名無しさん
05/05/16 22:15:27
いやだから、ディフォルト引き数で何が不満なんだ?

552:デフォルトの名無しさん
05/05/16 22:22:47
それぞれ特殊化で可能じゃない?もちろんそうするのが良いか悪いかは別。

553:デフォルトの名無しさん
05/05/16 22:26:17
>>551
例えばベクトルクラスがあります。
template< uint n >class vector;

これをインスタンス化したい場合、こういうふうに書きたいんです。
vector<2> v2 = vector<2>(5,1);
vector<3> v3 = vector<3>(5,1,6);
vector<4> v4 = vector<4>(5,1,6,3);
vector<5> v5 = vector<5>(5,1,6,3,9);
vector<100> v100 = vector<100>(5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9);

自然な欲求だと思います。

554:デフォルトの名無しさん
05/05/16 22:31:08
>>553
そういう時のためのstd::vectorではないかと思うのだが・・・・

555:デフォルトの名無しさん
05/05/16 22:34:16
static const uint initialValues[] = {5, 1, 6, 3, 9,};
std::vector<uint> v5 = std::vector<uint>(initailValues, initialValues + sizeof(initialValues) / sizeof(*initialValues));

556:デフォルトの名無しさん
05/05/16 22:34:58
その例なら
配列を初期化して、std::vectorにぶち込めばいいじゃん
どうしてもやりたいならBOOST_PPで特殊化

557:デフォルトの名無しさん
05/05/16 23:09:19
部分特殊化。以降略。なんか馬鹿みてえ。
#include <iostream>
#include <cstddef>

template <std::size_t N, typename T = int>
class vec {
T a[N];
public:
vec(T i) {
a[0] = i;
std::cout << a[0] << std::endl;
}
};

template <typename T>
class vec<2, T>
{
T a[2];
public:
vec(T i, T j) {
a[0] = i; a[1] = j;
std::cout << a[0] << ' ' << a[1] << std::endl;
}
};

int main()
{
vec<1> v1 = vec<1>(5);
vec<2> v2 = vec<2>(5,1);
}

558:デフォルトの名無しさん
05/05/16 23:21:18
特殊化はイヤというか面倒くさすぎるから、普通はこんなカンジだろうね

template<uint Dim> class vector {
double *const coord;
public:
vector(double x) : coord(new double[sizeof(char[Dim == 1]) * Dim])
 { coord[0] = x; }
vector(double x, double y) : coord(new double[sizeof(char[Dim == 2]) * Dim])
 { coord[0] = x; coord[1] = y; }
vector(double x, double y, double z) : coord(new double[sizeof(char[Dim == 3]) * Dim])
 { coord[0] = x; coord[1] = y; coord[2] = z; }
};

int main() {
vector<1> v(1);
vector<1> v1(1, 2); // error
vector<2> v2(1, 2);
vector<2> vv2(1); // error
vector<3> v3(1, 2, 3);
}


559:デフォルトの名無しさん
05/05/16 23:24:56
やはりコンストラクタのオーバーロードに落ち着くか。

560:デフォルトの名無しさん
05/05/16 23:25:18
>>
そうするまでもなく
普通に多重定義でいいと思うよ。

template <std::size_t N, typename T = int>
class vec {
T a[N];
public:

vec( T x, T y)
{
if( N > 0 )a[0] = x;
if( N > 1 )a[1] = y;
}

vec( T x, T y, T z)
{
if( N > 0 )a[0] = x;
if( N > 1 )a[1] = y;
if( N > 2 )a[2] = z;
}

};


561:デフォルトの名無しさん
05/05/16 23:27:04
ちなみに、 sizeof(char[Dim == 1]) ってのは、
Dim == 1 のときは、1 で、そうでなければ、コンパイルエラーね

562:デフォルトの名無しさん
05/05/16 23:59:25
どうも読みにくいので、直した

template<unsigned Dim> class vector {
 double coord[Dim];
public:
 vector(double x) {
  sizeof(char[Dim == 1]); // Dim == 1 でなければエラー
  coord[0] = x;
 }
 vector(double x, double y) {
  sizeof(char[Dim == 2]); // Dim == 3 でなければエラー
  coord[0] = x; coord[1] = y;
 }
 vector(double x, double y, double z) {
  sizeof(char[Dim == 3]); // Dim == 3 でなければエラー
  coord[0] = x; coord[1] = y; coord[2] = z;
 }
};

int main() {
 vector<1> v(1);
 vector<1> v1(1, 2); // コンパイルエラー
 vector<2> v2(1, 2);
 vector<2> vv2(1); // コンパイルエラー
 vector<3> v3(1, 2, 3);
}


563:デフォルトの名無しさん
05/05/17 02:55:12
おまえらの必死さに笑った。
C++の中途半端なtemplate機能でメンテ不能の駄作を量産してる様は、
まるでVBで汎用ライブラリを作る馬鹿とそっくりだな。

564:デフォルトの名無しさん
05/05/17 02:57:49
×メンテ不能
○俺に理解不能

565:デフォルトの名無しさん
05/05/17 07:37:28
あーあ、4,5,6って別々にするわけ?テンプレの意味ねー

566:デフォルトの名無しさん
05/05/17 07:41:46
テンプレートはマクロ
www.iba.k.u-tokyo.ac.jp/〜yanai/template_tips.html

567:デフォルトの名無しさん
05/05/17 10:05:48
>>563
まあ同意。boostとか見てても思うが、言語使用の範囲内でどうにかしようとするから無理が出てくる。
パズルとしては興味深いが、無理やりやってるからどうしてもキモくなる。
新しいプリプロセッサ作ったほうがマシな気がする。

568:デフォルトの名無しさん
05/05/17 12:24:00
>>566
典型的なアホっぽいが。

exportはComeauでサポートされていることすら知らんようだし。

569:デフォルトの名無しさん
05/05/17 12:40:07
>>566
> まず最も重要な事実は、templateはマクロであるということである。
そもそも、始めの仮定についてキチンと論証してない時点でアウトだな。


570:デフォルトの名無しさん
05/05/17 13:16:28
templateはマクロだよ。
マクロと聞いてCやC++のプリプロセッサ(やVBAなどアプリケーション内のスクリ
プティング言語)しか思いつかない人に向けた文章ではなかろ。



571:デフォルトの名無しさん
05/05/17 14:01:12
>ここではオブジェクト指向に則ったよいtemplateの使い方を模索する。
この時点で道を誤っている気が。

572:デフォルトの名無しさん
05/05/17 14:29:53
templateの明示的インスタンス化なんて、少し考えれば
使い道などろくに無い機能だとわかるだろうに
しかも使う必要も無い機能だし
それにこだわってる時点で、ダメだなそのページ

573:デフォルトの名無しさん
05/05/17 18:56:42
ネタをまじめに叩くなよ

574:デフォルトの名無しさん
05/05/17 20:39:55
ねたじゃねーし
templateはコンパイルする前に展開されるからマクロなの

575:デフォルトの名無しさん
05/05/17 20:42:50
コンパイルする前に展開しちゃったら
タイプセーフは無理じゃないの?

576:デフォルトの名無しさん
05/05/17 20:47:38
いいよわからん奴は無理に使うな

577:デフォルトの名無しさん
05/05/17 21:03:14
マクロで使える構文を限定的にして型を認識させたのがテンプレート

578:デフォルトの名無しさん
05/05/17 21:12:28
みんな好き勝手に「マクロ」の意味を定義して使ってるから、話が噛み合わない
だけでしょ。

579:デフォルトの名無しさん
05/05/17 21:56:51
おっと、ここで578が正式にマクロの定義とやらを教えてくれるらしいぞ

580:デフォルトの名無しさん
05/05/17 22:03:42
なにこの意味不明な反応

581:デフォルトの名無しさん
05/05/17 22:21:02
付き合うだけ無駄でつ

582:デフォルトの名無しさん
05/05/18 07:21:54
普通のマクロでも引数の数を変えられるようなことはできないから
>>553

583:デフォルトの名無しさん
05/05/20 00:28:48
VC7.1で
std::list<int>使うとポインタの保存のためか
std::vector<int>の3倍近いメモリ使うんだが、
省メモリな実装のlistって無理なのかな?


584:デフォルトの名無しさん
05/05/20 00:55:57
>>583
SGI STLのstd::slistなら、一方向リストだけど、少しでも少ないかも。

585:デフォルトの名無しさん
05/05/20 01:45:41
リストすら作りを理解してないのかよ。


586:デフォルトの名無しさん
05/05/20 12:25:58
std::vectorのresizeコストが気になるようならstd:;dequeとか

587:デフォルトの名無しさん
05/05/21 00:07:18
つうか双方向リストは最低2つはポインタが必要なんだから当たり前の気がするんだが

588:583
05/05/21 00:47:56
サイズは可変で大きい、挿入削除が定数時間(->list)、省メモリ(->vector)
を同時に満たしたかったので...
とりあえず挿入削除の速いlistを選択したけど、以外とメモリ食うって分かった。

小規模のvectorをlistで繋ぐか584さんのslistつかうのがいい気がしてきた。
双方向リストだとポインタが64bit化したらさらに事態は悪化するのも気になるし...


589:デフォルトの名無しさん
05/05/21 00:53:20
だから小規模なvectorをつなぐぐらいならdeque使えってばよ

590:デフォルトの名無しさん
05/05/21 00:54:03
>>587
要素が int で、双方向のポインタがあるわけで
それぞれサイズが同じなら、int の 3倍ですね。
>>585 も指摘してますが、糞当たり前です。

591:デフォルトの名無しさん
05/05/21 00:54:46
>588
データ構造の勉強からやり直して来い。

592:デフォルトの名無しさん
05/05/21 00:55:27
s/int の/1要素あたり int の/

593:デフォルトの名無しさん
05/05/21 00:56:22
>>588
中身の小さいオブジェクトを入れると、相対的にlistはポインタなどの管理部分が
大きく見えてしまうからねえ。
ケースバイケースで使い分けるしかない。
それとstd::slistのiteratorは、forward iteratorなので、bidirectional iteratorのlist
に比べると実行効率の悪いメンバ関数がいくつか存在するから、その点もよく確かめてね。

594:583
05/05/21 01:04:49
dequeだと
中間への挿入、削除した場合に
参照と反復子が死滅。



595:デフォルトの名無しさん
05/05/21 01:05:46
>>588
テキストエディタみたいに、挿入が同一箇所に連続して発生するようなら
ギャップベクタを検討するといいかも

596:デフォルトの名無しさん
05/05/21 01:34:23
>>594
それが問題になるなら、もう list しかないんじゃないかなぁ。
「小規模のvectorをlistで繋ぐ」なんてのも、全然ダメだろ。

597:デフォルトの名無しさん
05/05/21 01:43:48
もはやtemplateの話題じゃなくて、「データ構造とアルゴリズム」の世界だな。

598:デフォルトの名無しさん
05/05/21 02:11:25
listとかvectorはあるのに、より優れた概念のS式がないのはおかしい

599:デフォルトの名無しさん
05/05/21 03:42:02
>>598
あなたね(汗
インタプリタじゃないんですから。

600:デフォルトの名無しさん
05/05/21 05:55:52
>>599
もっと詳しく。

・・・って言っても無駄か。
何もわかってないくせに噛み付いてるの見え見えだもんな。

601:デフォルトの名無しさん
05/05/21 08:25:20
S式ってツリー構造じゃ無かったっけ?違った?

602:デフォルトの名無しさん
05/05/21 08:41:31
>>600
赤黒木だけじゃ足りないってのかい。

603:デフォルトの名無しさん
05/05/21 09:18:31
>>597
STLネタがそっちに向かうのは自然だと思うけど?

604:デフォルトの名無しさん
05/05/21 09:22:59
> つうか双方向リストは最低2つはポインタが必要なんだから当たり前の気がするんだが
直前の要素のポインタと直後の要素のポインタの排他的論理和演算結果を保持しておけ。
そうしておけばポインタ1つで双方向からリストをたどることができる。

実行時にそれなりのコストはかかるが、、、

605:デフォルトの名無しさん
05/05/21 10:01:07
>>604
結局サイズは変わらないわけだが。
しかも「ポインタ同士のXOR」?ワケワカラン。

606:604
05/05/21 10:23:45
以下のようなリンクリストがあったとする。

A‐B‐C

この時、B のポインタ領域には &A ^ &C となる値がセットされることになる。
順方向でA、Bまで読み込んできた場合、Aのアドレスは判っているはず。
このため、&A ^ (&A ^ &C) を計算することでCのアドレスが取得できる。

同様に逆方向でC、Bまで読み込んでいる場合、Cのアドレスは判っているため、&C ^ (&A ^ &C) を計算することでAのアドレスが取得できる。

これが magic list というデータ構造。


607:デフォルトの名無しさん
05/05/21 10:35:12
>>606
代償としてイテレータのサイズが大きくなるから、使い道は微妙だけどな。

608:デフォルトの名無しさん
05/05/21 10:43:01
>>606
ふーん。
std::list の実装に使われてるのは見たこと無いんだけど、
標準コンテナの実装としては何か問題があるのかな?

と考えたら、イテレータを取得した後に要素の削除・追加をするとマズイような気がした。

609:デフォルトの名無しさん
05/05/21 10:44:00
>>604
リストを変更しないときのコストはたいしてかからないんじゃないか。
簡単なループの場合、movl (%eax),%eax が xorl (%eax),%eax になるだけだろう。

>>607
イテレータのサイズなんて問題になることがそうそうあるとは思えんが。

前後に追加削除があるとイテレータが無効になってしまうから
std::listとはコンパチにならなくなることの方がまだ問題になりそうだ。


610:604
05/05/21 10:50:55
>>607
イテレータのサイズとリンクリストに保持される各要素のデータサイズを同列で比較するのもどうかと思うが。

イテレータにポインタを2つほど追加したところで、8バイトしかサイズは増えない。
(処理が複雑化する分、イテレータオブジェクトのサイズはもう少し増えると思うが。)
しかし、双方向ポインタにしてしまうと、各要素毎に4バイトの投資が必要となる。


611:604
05/05/21 10:58:43
>>608>>609
確かにイテレータの取得後に前後の要素が追加削除されると痛い。
排他制御の問題を抱え込むから、std::list との互換性は考えない方が吉かと。

612:デフォルトの名無しさん
05/05/21 11:12:46
>>609
> 簡単なループの場合、movl (%eax),%eax が xorl (%eax),%eax になるだけだろう。

訂正。これ間違い。xor+mov*2(or xchg)になるな。




613:デフォルトの名無しさん
05/05/22 00:18:22
> サイズは可変で大きい、挿入削除が定数時間(->list)、省メモリ(->vector)
データの格納にset使うのってやっぱダメなのか?
setの中身はconst扱いだけど、外してswapして取り出して消して使ってるけど。
挿入時もヌルデータ入れて跡で要素をswapしてるんで無駄なコピーも出ない用に工夫して、、、
、、、、

vectorはサイズ増えると勝手に自分のコピー作るんで、reserveしなきゃならんので嫌だ。
lispは探索が遅いし。mapはそんなものに使うのもったいないし。

結論 : set使え!

614:デフォルトの名無しさん
05/05/22 00:31:16
setが泣いてるぞ

615:デフォルトの名無しさん
05/05/22 00:31:37
listのメモリ効率が気になるような状況でsetなんか使えるかよ
つーか、dequeって要素へのアクセスもそこそこ速くサイズ変更のコストも最小限なのになんで使われんのか。

616:デフォルトの名無しさん
05/05/22 03:41:02
>>615
dequeって要素へのアクセスもそこそこ速く
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
環境によってはlist並みに遅いわけですが何か?
OSやCPUは敢えて書かないが、STLportとかSTLportとかSTLportとか。

617:デフォルトの名無しさん
05/05/22 06:50:59
>>606
C++ でポインタにビット毎の論理演算なんて
吉外じみた真似、よく平気で出来ますね。

618:604
05/05/22 08:36:41
>>617
坊やだな、、、
ポインタと言えど所詮はビット列なのだよ。

619:デフォルトの名無しさん
05/05/22 08:39:59
>>618
reinterpret_castとか使わないといけないんだろ?
環境依存イクナイ(・A ・)!

620:デフォルトの名無しさん
05/05/22 08:55:43
>>606
面白いなぁ

621:604
05/05/22 08:55:52
>>619
reinterpret_castが即、環境依存につながるとは新鮮な考え方だな。
同じ環境内でキャストして、同じ環境内で元に戻すのであれば、環境依存も何もないだろうに(それを環境依存というのなら、コンパイラが吐くコードはすべて環境依存になるぞ)。
それとも、そういうことすら期待できない処理系が現存するというのか?
(そんなのが出てきた時点で reinterpret_cast は言語仕様から外されるだろうて。)

622:デフォルトの名無しさん
05/05/22 09:07:29
>>621
愉快な香具師だなお前。
C++の実装と進化の§14.3.3(P420)読んでみろ。

623:デフォルトの名無しさん
05/05/22 09:09:30
>>622
○C++の設計と進化
×C++の実装と進化

それから、規格票を優先しろ。

624:604
05/05/22 09:17:26
その本は持ってない。
引用の範囲内だろうから、出典を明記して引用してくれ。
内容を咀嚼して説明してくれてもよいぞ。


625:620
05/05/22 09:35:20
俺の面白いは純粋な意味であって、622と同じ意じゃないですよ

626:デフォルトの名無しさん
05/05/22 09:38:55
5.2.10 Reinterpret cast

4 A pointer can be explicitly converted to any integral type large enough to hold it.
The mapping function is implementation-defined [Note: it is intended to be unsurprising
to those who know the addressing structure of the underlying machine. ]

5 A value of integral type or enumeration type can be explicitly converted to a pointer.
A pointer converted to an integer of sufficient size (if any such exists on the implementation)
and back to the same pointer type will have its original value; mappings between
pointers and integers are otherwise implementation-defined.

要するに規格としてはポインタ型を整数型にreinterpret_castして
その値をそのままポインタ型に戻す操作以外は完全に実装依存

627:604
05/05/22 09:57:53
「5.2.10 Reinterpret cast」の真意は、整数型にキャストし、演算後の《変更された値》をポインタにキャストし戻したとしても、それはポインタとして無効であるということだけだと思うぞ。
一例を挙げると、配列の特定要素を指すポインタを整数型に変換した後、インスタンスオブジェクトのサイズ分だけ値を加算し、ポインタ型に戻したとしても、次の要素へのポインタにはならないぞ、、、という。

Magic listにおける A-B-C という例において、Bに保存されている値はAのアドレスとCのアドレスを特定のルールで「エンコード」しただけの整数値であり、デコードすることにより元々のポインタ値を復元することが可能なはず(てーか復元できなければ意味はない)。
このため、上記の§5.2.10の規則には抵触しないと思うが?
むしろ「A pointer *can be* explicitly converted to any integral type」と書かれている以上、そのことが保証されているとも取れる。

integral typeにして何の演算も許さず、元のポインタに戻すことしかできないのであれば、そもそもキャストする意味ないし。 まさかシリアライズするのか?、、、ってそれはあまりにも危険だしな。


628:デフォルトの名無しさん
05/05/22 10:18:14
>>626
ん?問題ないんじゃない?

同じポインタからは同じ整数になり、
同じ整数からは同じポインタになるっていう射影だよね。
この規格表のいいたいところは要するに、
アドレスが16違っている2つのポインタを、
整数に直した時も16違っているかどうかはわからないよ、
というだけの話じゃん。


629:626
05/05/22 10:20:55
>>627
>Magic listにおける A-B-C という例において、Bに保存されている値はAのアドレスとCのアドレスを特定のルールで「エンコード」しただけの整数値であり、デコードすることにより元々のポインタ値を復元することが可能なはず(てーか復元できなければ意味はない)。
>このため、上記の§5.2.10の規則には抵触しないと思うが?
>むしろ「A pointer *can be* explicitly converted to any integral type」と書かれている以上、そのことが保証されているとも取れる。

5.2.10/5はポインタを整数にreinterpret_castした後,その整数値を「そのまま何の演算も行わずに」
元のポインタ型に再度reinterpret_castした場合,元のポインタ値に復元されることを保証するものです.
604さんのmagic_listでは排他的論理和演算を取るため「そのまま」ではないものの
5.2.10/5は明らかにreinterpret_castによるpointer <-> integerの1対1写像を保証しているものと
読めるため確かにそのとおりですね.626は621に対する指摘のつもりでしたが,
いやはや指摘がまったく見当違いどころかむしろ621が正当である根拠になりえますね.
これまた大変失礼しました.

>>628
上に同じです.失礼しました.

630:デフォルトの名無しさん
05/05/22 12:18:47
magic list はネタとしては面白いが、現実には滅多に使われない
データ構造だな。この手のネタは Hakcer's Delight とか Knuth
センセの本を読むとイロイロ転がってるよ。

あと、現実のプログラミングだと、list に int 一個だけ入れるのも
珍しい気がする。手元のコードをいくつか見直してみたが、わりと
大きめの構造体を繋ぐか、スマートポインタを入れることが多い。
いずれにしてもポインタ二個分のメモリなんて誤差って感じ。

631:デフォルトの名無しさん
05/05/22 13:39:00
珍しいかどうかは、ともかく
メモリ云々行ってた奴は、たぶん初心者だから
初心者の戯言を、あまり真に受けないほうが

632:デフォルトの名無しさん
05/05/23 09:43:55
結論はvector使え、でいいのか?

633:デフォルトの名無しさん
05/05/23 09:54:29
>>632
いい

634:デフォルトの名無しさん
05/05/23 12:40:40
magic list は所詮オナニー

635:デフォルトの名無しさん
05/05/23 18:35:46
ここはジェネリックプログラミングの話題じゃないのか?

636:デフォルトの名無しさん
05/05/24 00:13:26
>>635
テンプレートの話題ですよ。尤も、スレタイも読めないなら
このレスも読めない可能性、大。

637:デフォルトの名無しさん
05/05/24 03:37:35
暇つぶしに作ってた、ヘボコンパイラは出来上がったから
今度は、マジックリストクラステンプレートでも作ってみようかな
作ったらほしい人いる?

638:デフォルトの名無しさん
05/05/24 08:09:05
>>637 興味はある

639:デフォルトの名無しさん
05/05/24 09:47:05
学術的な興味なら。
ソースより測定結果をみたい。listやvectorとの比較つきで。

640:デフォルトの名無しさん
05/05/24 15:44:00
というか作りかけてる・・・

641:デフォルトの名無しさん
05/05/24 22:41:55
できたら
>>639もぜひ。

642:デフォルトの名無しさん
05/05/24 23:45:11
>>640
637だけど、あなたに任せます

643:デフォルトの名無しさん
05/05/25 01:39:21
小規模だけど多次元配列のポインタがどうしても必要で、newも使いたくないから
std::vector<std::vector< ...> >
とかで書いてみたんだけど、4次元ぐらいからコンパイル時間が凄くかかる。
ま、コンパイル時に何がおきてるか想像すりゃ当たり前といえば当たり前だし、
コンパイル時だけの問題なので気にしなきゃいいんだけど、
環境になるべく依存しないで(boostとかは使えないし、VC,gcc両方通す必要あり)、
効率の良い方法がありまつかね。std::deque使ってもかわらなさそうだし。



644:デフォルトの名無しさん
05/05/25 01:49:02
>>643
その「多次元配列」のインターフェースを必要最小限に絞って、
pimpl なり抽象インターフェースなりでコンパイル単位を分ける。
基本だな。

645:デフォルトの名無しさん
05/05/25 02:06:06
>>644
dクス。
pimplイディオムは詳しくないので、Exceptional C++でも読んでみまつ。

646:640
05/05/25 02:46:33
URLリンク(kansai2channeler.hp.infoseek.co.jp)
面倒だったのでBoost使いました.1.32.0が必要です.すいません.
VC++7.1とGCC3.4.2(mingw)でコンパイル確認しています.
勢いだけで突っ走ったので激しく読みにくいコードで申し訳ないです.
イテレータが安定じゃないのでsplice系がイテレータ返さないと
使い物にならないので,イテレータ返すようにしてます.
std::listのインターフェースであと実装していないのはsortと演算子だけです.
でも今日はもう気力残ってません.パフォーマンス測定もしかりです.おやすみなさい.

647:デフォルトの名無しさん
05/05/25 04:02:34
void reverse() // throw()
{
head_ = decode(sentry_.code, head_);
}

感動してしまった。

648:デフォルトの名無しさん
05/05/26 03:43:21
URLリンク(kansai2channeler.hp.infoseek.co.jp)
微妙なバカチョンと例外飛んだときのバグを直しました.多分これで完璧なつもりです.
ただ,相変わらずsortだけ面倒なので実装してないです.
指摘されていたこととは言え,このデータ構造イマイチ利点がぼやけてますね.
特にアラインメントの関係でノードのサイズが普通のリストのそれと
同じになってしまう(32-bitマシンでmagic_list<double>とか)場合もあったりで散々かも.
唯一,647さんが指摘されているように要素順の反転を定数時間でできるのが
大きな特色ですけれど,それがうれしい状況ってあるんでしょうか・・・.

649:デフォルトの名無しさん
05/06/06 11:28:39
質問です。
「具現化によって生成された実体」 = 「ユーザー定義ではないスペシャライゼーション」
という理解でいいの?

650:デフォルトの名無しさん
05/06/07 22:08:43
"template テンプレート パラメータ"の意味が理解できないッス。
"Modern C++ Design" P11 の以下のコードなんですけど、

template <template <class> class CreationPolicy>
class WidgetManager : public CreationPolicy<Widget>
{
...
}

ここで template <class> に対して私の頭の中で
シンタックスエラーが発生します

template<class T> // ノーマル
template<> // 特殊化
template<class T=int> // デフォルト引数
template<class T, int=10> // 特殊化とデフォルト引数

というシンタックスは理解できています。
template <class> って何者? 誰か教えてください。

651:デフォルトの名無しさん
05/06/07 22:12:38
省略されてるだけ。
template <class /*T*/>
class foo;

652:デフォルトの名無しさん
05/06/07 22:27:41
>>651
サンクスです。とすると何らかの型を受け取るけど、
その型の情報は無視するよ、っていうことなんですね。
これをもとにもう一回読んでみます。

653:デフォルトの名無しさん
05/06/07 22:32:56
>>650
int f(int i);
int g(int); // これも脳内エラーが出るか?

654:デフォルトの名無しさん
05/06/08 00:28:08
>>650

例えば、

template< template<class T, class A> class Vector>
struct hoge
{
typedef T value_t;
};

typedef hoge<std::vector> hv_t;

としても、この時点では”T"はまだ決まってないわけだから
名前付けても使えないのです。
無論、”Vector"もこのままでは使えません。

実際の使用には

template< tempalte<class,class> class V>
struct hoge
{
template<class T,class A>
struct bind
{
typedef V<T,A> type;
};
};

typedef hoge<std::vector> hv;
typedef typename hv::template bind<int,std::allo..>::type
のように使うことになりますね。


655:デフォルトの名無しさん
05/06/08 00:31:15
補足ですが、

使えない == typedefできないということです。


656:デフォルトの名無しさん
05/06/08 00:41:11
>>654-655 とても650の理解を助けるとは思えない。

657:デフォルトの名無しさん
05/06/08 01:10:19
間違ったことは言ってないが、質問の答えとしては完全にズレてるな。

658:654
05/06/08 01:22:29
>>656-657

この場合
>"template テンプレート パラメータ"の意味が理解できないッス。
と書いてあるところから、名前云々は関係ないと思うのですが・・

659:デフォルトの名無しさん
05/06/08 10:35:01
>>658 会話になってないな。もういいから喋るな。

660:デフォルトの名無しさん
05/06/08 21:38:27
>>650です。
皆さんありがとうございます。
>>654さんのご意見もとても理解の助けになりました。

661:デフォルトの名無しさん
05/06/09 08:01:15
typedf templateってどうなったの?

662:デフォルトの名無しさん
05/06/09 08:13:16
template< template<class T, class A> class Vector>
struct hoge
{
typedef T value_t;
};
template<class B> typedef hoge<std::vector<B> > hv_t;
typeof(hv_t<int>::value_t) i;

みたいにtypedefの一文をテンプレート化できるんだっけ。

663:デフォルトの名無しさん
05/06/09 08:32:30
>>662
それはだめだろ。
template-templateパラメタのtemplateパラメタ(この場合T)
に言及するのは意味的におかしい。

664:デフォルトの名無しさん
05/06/09 08:43:39
こうじゃないか?

template <typename> struct hoge;
template <template <typename, typename> class V, typename T, typename A>
struct hoge<V<T, A> >
{
typedef T value_t;
};
template <typename T> typedef hoge<std::vector<T> > hv_t;
hv_t<int>::value_t i;

665:デフォルトの名無しさん
05/06/09 08:49:01
typedef templateを導入するなら変数templateや名前空間templateも欲しい。

と無責任に言ってみるテスト。

666:デフォルトの名無しさん
05/06/09 08:56:13
>>664
あーなるほど。C++よく分らないから適当に書いてみたんだけどそれなら理解できるw

>template <template <typename, typename> class V, typename T, typename A>
> struct hoge<V<T, A> >
こうやって部分的特殊化で各パラメータ間の関係を表現できるのね。

>>663
>template <typename T> typedef hoge<std::vector<T> > hv_t;

問題はこの部分で、パラメータvector<T>の高階性(?!)を維持してくれるのかどうかってところかねえ。

>>665
変数templateとはどんなもんでしょ?

667:デフォルトの名無しさん
05/06/09 11:34:08
もしも変数テンプレートがあったとしたらこんな感じ?
template <typename T> const T *NULL = 0;

int *pi = NULL;
char *pc = NULL;

#include <cstdio>
int main() {
  std::printf("%p", NULL<void *>);
}

668:デフォルトの名無しさん
05/06/09 11:59:30
>>667
>int *pi = NULL;
>char *pc = NULL;
これを許すとまた規則が複雑になるな。

669:デフォルトの名無しさん
05/06/09 12:14:33
class null {
public: template<typename T> operator T*() const { return 0; }
};

const null NULL;

int *ip = NULL;
char *cp = NULL;

printf("%p", (void*)NULL);

でいいような気がす

670:デフォルトの名無しさん
05/06/09 12:16:52
誰もそんな話ししてないわけだが

671:デフォルトの名無しさん
05/06/09 13:24:53
>>667
引数とるコンストラクターはどうなるんだ。

672:デフォルトの名無しさん
05/06/09 13:52:48
typedef template ムチャ欲しいな。

673:デフォルトの名無しさん
05/06/09 14:26:04
>>667
今のC++の型の取り扱いにあわせると

template<typename T> const T *NULL = 0;

は,右辺がリテラルの0でこれは型がintだからポインタ型に変換できず,
Tをどの型でinstantiationすれば良いのか判断できずコンパイルエラーになる,
っていう扱いが妥当だと思いますよ.
もうちょい厳密に変数テンプレートを定義しようとすると,
結局,型推論のためのautoキーワードの拡張

auto a = b; // typename(b) a = b; の構文糖

と同じになると思います.Andrew Koenigあたりがこのautoキーワードの代わりに
>>667の構文を提案してたはず.

674:デフォルトの名無しさん
05/06/09 14:35:13
>>673
>>667の代わりに、
template <typename T> struct wrap{static const T *null;};
template <typename T> const T *wrap<T>::null = 0;
と書けることを考えると、今の扱いなら、

・template <typename T> const T *NULL = 0;
の時点では何も起こらない。
・printf("%p" NULL<void *>);
の点でインスタンス化が引き起こされ、void *const *を0で初期設定しようとし、成功。

が妥当じゃないのか?

675:デフォルトの名無しさん
05/06/09 14:50:45
>>670
そうでなくて、必要性が全く感じられないと言っている
まともな利用例ぐらい出さないと

676:デフォルトの名無しさん
05/06/09 14:56:07
>>674
その使い方だと常に明示的にインスタンス化しないといけない
(NULLを利用するたびに型パラメータを与えないといけない)わけですよね?
それは利用範囲が著しく限られませんか?

677:667
05/06/09 15:03:10
ところで俺は変数テンプレートは全く要らないと思うんだけどな。
俺も669と同じようなのを考えたことはあるけど。

678:デフォルトの名無しさん
05/06/09 15:10:28
>>676
使い道がないのは同意。
ただ、仮に現在のテンプレートの延長で「変数テンプレート」なるものを定義するなら、
>>674で言ったようになるはずだと思った。
>>673のような機能を導入するなら別の名前・構文を考えるべきだと思う。

679:デフォルトの名無しさん
05/06/09 15:26:38
型推論はされるとして、
NULLみたいに初期化子に使うとちょっと面白そうな…

クラス階層のあるところでPTHREAD_MUTEX_INITIALIZERみたいなやつ。

680:デフォルトの名無しさん
05/06/09 15:29:21
>>678
確かに「変数テンプレート」という名前は非常にまずいですね.
ただ構文については既存のキーワード使うとするとこれぐらいしかないような気がします.

681:デフォルトの名無しさん
05/06/12 15:01:48
アドビのオープンソースってど?流行ると思う?
STL、boostを基に、ウィンドウをスクリプトから生成する画期的システム
仮想マシンを実現とか、内容は理解を超えていた (つД`)

いわゆるチョット修正のときに威力を発揮すると思う
SEはどんな些細なこともPGに要望しなけりゃならない
PGは思いつきの修正のために仕事が増えるばかり
だれか人柱になってください、やっぱアドビ待ちなのかな

682:デフォルトの名無しさん
05/06/12 17:16:13
>>681
AdamとEve( URLリンク(opensource.adobe.com) )のことか?なかなか
普及は難しいんじゃないかなぁ…

683:デフォルトの名無しさん
05/06/13 00:40:41
質問です。
BCC 5.5上のテンプレートのバグはどのようなものが
あるのでしょうか。

・・・特に大きいタイプリストを渡すと、他の特殊化に指定
したクラスが別のクラスに化けるとか、そんなのないですか?

684:デフォルトの名無しさん
05/06/13 10:45:49
>>683
質問するときはやりたいこと、実際にやったことを書いた方が良い。

685:デフォルトの名無しさん
05/06/13 14:20:43
>>683
どういうバグかは知らんがboostが満足に使えない。

686:683
05/06/13 21:39:52
自己解決しちゃいました。

経緯だけ説明しますと、Modern C++ Designのマルチメソッドを
自分の使いやすい形に改良して使っていたんです。で特殊化の
際タイプリストを
template<..,class Head,class Tail>struct
Dispatcher<...,Typelist<Head,Tail>,...>{
...省略
};
と展開していて、6ほどの長さのタイプリストをわたしたところエラー吐かれました。
(5つまでは普通にコンパイル&動作しました)

これを
template<..,class TList>struct
Dispatcher<...,TList,...>{
...省略
};
としHeadにアクセスするときTList::Head,Tailにアクセスするときは
TList::Tailとするようにしたら今度は何十の長さでもコンパイルできました。

前者のコンパイルの仕方にバグがあるんでしょうかね・・・

687:デフォルトの名無しさん
05/06/13 23:51:10
BCCなんか使うなよ

688:デフォルトの名無しさん
05/06/14 17:45:57
もしかして、クラステンプレートのメンバ仮想関数って勝手に実体化される?

689:デフォルトの名無しさん
05/06/14 17:58:42
>>688
どんなコードでそう思った?

690:688
05/06/14 18:10:23
ものすごく単純化すると、
class base
{
public:
virtual void foo() = 0;
};
template <class> class derived : public base
{
public:
virtual void foo() { std::cout << "呼ばれた\n"; }
};
int main()
{
derived<int> d;
static_cast<base&>(d).foo();
}
こんな感じ。

691:デフォルトの名無しさん
05/06/14 18:24:16
>>690
それってderived<int>型の変数dを宣言したからderived<int>が実体化されているだけのように見えるが。

692:688
05/06/14 18:28:53
derived<int> が実体化されるのと
derived<int>::foo が実体化されるのは別じゃないですか?
クラステンプレートのメンバって呼ばれるまで実体化されませんよね?

693:デフォルトの名無しさん
05/06/14 18:31:57
>>688
規格では詳しくは規定されていないっぽい。
実際は
・derived<int>のインスタンスが宣言された
・derived<int>*からbase*の変換が行われた
のいずれかをトリガとして、仮想関数をすべて実体化することになると思う。

694:688
05/06/14 18:40:33
>>693
サンクス。未定義ってことですか。
一応、明示的に実体化しておいたほうがよさそうですね。

695:デフォルトの名無しさん
05/06/14 18:47:45
>一応、明示的に実体化しておいたほうがよさそうですね。
なんでそうなる?

ついでに、「未定義」と「未規定」は違う。

696:688
05/06/14 18:50:17
ん?
規定はされていなくても、正常に動くことは保証されているってことですか?

697:693
05/06/14 18:57:55
言い方が不正確だったな。
規格には、「メンバ関数は、その定義が必要とされるとき実体化される(意訳)」とある。
で、virtual関数については、いつ「定義が必要とされる」か正確に規定している部分が(俺の見た限りでは)なかった。
従って、virtual関数の正確な実体化のタイミングは規定されていないことになる。
それでも、「必要」になり次第実体化されることは保障される。

698:688
05/06/14 19:22:06
あー、なるほど。
規定されていないのは実体化されるタイミングだということですね。
どうもありがとうございました。

699:デフォルトの名無しさん
05/06/26 18:25:16
int k = 0;
for (vector< set<int> >::iterator it = v.begin(); it != v.end(); ++it)
it->insert(k++);

を boost::lambda か何かを使って for_each でシンプルに書けませんか?
メンバー関数に bind する仕方がよく分からないんですが・・・

700:デフォルトの名無しさん
05/06/26 19:33:36
>>699
typedef std::set< int > set_type;
typedef std::vector< set_type > vector_type;
void f( vector_type& v )
{
 using namespace boost::lambda;
 int k = 0;
 std::for_each(v.begin(), v.end(), (protect(bind((std::pair<set_type::iterator,bool> (set_type::*)(int const&))(&set_type::insert), _1, var(k)++)))(*_1));
}

○ boost::lambda か何かを使って
○ for_each で
× シンプルに

701:700
05/06/26 19:49:39
メンバ関数に限らず、オーバーロードが絡むと lambda は使いにくいな。


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

5381日前に更新/262 KB
担当:undef