トップページ⇒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 あたりに。
0271デフォルトの名無しさんNGNG
266です。
>>268>>270 やっはりそうですよね。分かりやすく書くことを心がけるようにします。
0272デフォルトの名無しさんNGNG
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");
}


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

明示的にコンストラクタを呼び出すには、コンストラクタ初期化子を使う
しかない。
0274デフォルトの名無しさんNGNG
>A(const char* c) :string(c)
これ、: m_str(c) の間違いではなくて?
こういう書き方あるの?
0275デフォルトの名無しさんNGNG
>>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
}
0276デフォルトの名無しさんNGNG
明示的に呼ぶ場合、
this->A::A();
これならOKなのでは?
0277デフォルトの名無しさんNGNG
>>276
エラーっしょ。
0278デフォルトの名無しさんNGNG
>>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());
}
0279デフォルトの名無しさんNGNG
>>278
コンパイラは何を使った?Borland-C++5.6.2及びgcc3.2(MinGW)は
エラーが出て通らないけど。
0280278NGNG
>>279
そうなの?
VC5(苦笑)でつ。
M$オンリーの機能なのか?
エラーはどんなの?
0281デフォルトの名無しさんNGNG
>>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

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

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

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

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

>>286
ちょっと、目の付け所がいまいち
0288デフォルトの名無しさんNGNG
>>287
そっか。そう言われればそうだな。途中でリコンストラクトした事にはコンパイラ
は気づいてないだろうからね。
0289デフォルトの名無しさんNGNG
>>269 ありが�d
0290デフォルトの名無しさんNGNG
>>284
× new(this)T(param);
○ new (static_cast<T*>(this)) T(param);
0291デフォルトの名無しさんNGNG
// こんな感じ?
#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)
}
0292デフォルトの名無しさんNGNG
>>291
実行結果が次のようになったのだが、大丈夫だろうか?

Base::Base()
エロ::~エロ() //←これヤバくない?
Base::~Base()
Base::Base()
エロ::エロ()
エロ::エロ(int)
エロ::~エロ()
Base::~Base()
0293デフォルトの名無しさんNGNG
>>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);
}
0294293NGNG
今気づいたが、
テンプレート使う必然性無く、まったくレス違いなネタのような……
0295デフォルトの名無しさんNGNG
>>293
ををををぉぉぉぉなんとトリッキーな。

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

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

>>293
飛び入りな者でスミマセン。
0297デフォルトの名無しさんNGNG
>>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
0298デフォルトの名無しさんNGNG
gcc3.2(MinGW)は次のようにしたらコンパイルできて、実行結果は以下の通りです。

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

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

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

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

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

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

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

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

int main()
{
    func();
}

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

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

こうするはず
0318310NGNG
>>314
template <class T> はHoge に付いているんで、メンバじゃない func() には関係ないと思うけど。

>>315、>>316
動きました。でもなぜ?
func() は普通の関数じゃないの? テンプレートじゃない普通の関数をインスタンス化?
0319デフォルトの名無しさんNGNG
> テンプレートじゃない普通の関数

どうしてそう思うのか訊きたいのだが
0320316NGNG
だから規格書嫁って。
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.
0321310NGNG
>>319
フレンド関数が func() が テンプレート Hoge のメンバじゃない、っていうのは正しいですよね。
Hoge のtemplate <class T> は、クラスそのものとメンバに対してしか影響せず、パラメータに依存しているわけでもない func() とはまったく関係ないはず。
func() 自体も関数テンプレートとして定義されているわけじゃない。

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

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);
}
0327デフォルトの名無しさんNGNG
>>326
質問内容と貼り付けるソースを対応させてくれ。
ソースがいろんな(たぶん余計な)要素を含みすぎて
何を答えて欲しいのかがイマイチつかめん。

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

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

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

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

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

プログラムの流れでたまにしか出てこない、いろんな種類のファクトリをはじめからメモリに確保するのが嫌だったのです。
でも実行時に登録するには、
・コンパイラが自動的に実行してくれるグローバルな領域に置かれた命令による登録(シングルトンが必要)
・どこかにリストアップしておく。
のどちらかしか無いように思います。
用語が滅茶苦茶だと思いますがすいません。
0337sageNGNG
>・コンパイラが自動的に実行してくれるグローバルな領域に置かれた命令による登録(シングルトンが必要)
グローバルはおかしいかな。
cppファイルの頭の部分に書く
const bool registered = Singleton::Register(objType,CreateCallback);
な感じのやつのことです。
0338デフォルトの名無しさんNGNG
ファクトリの百や二百、メモリを使用してるうちに入らんと思える私は幸せなのでしょうか。
0339332NGNG
私もです。しかもせいぜい10個くらい。
0340デフォルトの名無しさんNGNG
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を使う状況というのがどう
いう場合なのか知りたい。
0341デフォルトの名無しさんNGNG
>>340
Aが派生して使うような型じゃない場合。
0342デフォルトの名無しさんNGNG
>>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));
}
0343デフォルトの名無しさんNGNG
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)); // だめ
}
0344デフォルトの名無しさんNGNG
どうして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;
}
}
0345デフォルトの名無しさんNGNG
>>343
試さずに書いてるが、
boost::compose_f_gx( boost::bind( &A::print, _1, 1 ), &boost::any_cast<A&> );

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

後環境も何も書いてないからこれ以上は無理
0349デフォルトの名無しさんNGNG
Lindows
0350デフォルトの名無しさんNGNG
>>345
ありがとうございます!

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

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

boost::any_castは依存関係の把握はできないかもしれませんので、ポリモルフィズム
には使わないようにします。
0351デフォルトの名無しさんNGNG
ところで C++ Templates [ http://www.josuttis.com/tmplbook/tmplbook.html ;] は既出なのか?
0352名無しさん@EmacsNGNG
げ、ホントだ、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
0353デフォルトの名無しさんNGNG
>>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とかの方がマシだしなぁ。
0354デフォルトの名無しさんNGNG
>>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と組み合わせていろいろと面白い事をやらせようとしていた
のだが、使えねー。まあだめならだめで昨日から悩み続けていた事が解決
したのでいいのだが。
0355デフォルトの名無しさんNGNG
スマソ>>354は>>352さんに対するレスです。
0356デフォルトの名無しさんNGNG
すごく簡単な所でつまづいています。どこがおかしいのでしょうか?

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);
}
0357デフォルトの名無しさんNGNG
自己解決しました。うーん?直感的には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));
}
0358デフォルトの名無しさんNGNG
こんな簡単なプログラムがコンパイルできません。どこがおかしいのか
わかりますか?コンパイラは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);
}
0359デフォルトの名無しさんNGNG
358です。非常に不本意ながら、自己解決しました。
#include <cmath>を#include <math.h>にして、std::sinをsinにすれば通ります。

しかし、ここで当然疑問が沸きます。なぜstd名前空間に包まれているsinが
std::transformに適用できないのか、どうしてもわかりません。何のための
<cmath>なんでしょうか?
0360デフォルトの名無しさんNGNG
>>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 ) と同じ意味になるものなので期待通りになる。
0361デフォルトの名無しさんNGNG
>>359
C では double sin(double x); しかないが、C++ では
double sin(double x);
float sin(float x);
long double sin(long double x);
とオーバーロードされてて、どれかわからんので困ってるのでは?
0362デフォルトの名無しさんNGNG
>>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));
}
0363デフォルトの名無しさんNGNG
typedef struct
{
int id;
double value;
} BANK;

std::list<BANK> blist;

みたいなlistがあって、こいつを構造体BANKの中のvalueの値で
sortしたい(valueの値が大きい順に)場合、どうしたらよいのでしょうか?
blist.sort()を使う方を教えてください!!
0364デフォルトの名無しさんNGNG
>>363
sortに引数を渡せ。
0365352NGNG
>>353,354
むむむ、なるほど。情報サンクスコ
なんか大抵の場合はポリモーフィズムかテンプレート使えばいい感じですなぁ・・・
>>853氏の例をちょっといぢってみたんだけど、 6 を 6.0f にするだけで氏ぬのね。
typeid 使うとこの辺(double, float とかポリモーフィズムとか)が問題になって来るわけか。
なるほど、なるほど。勉強になりますた。
0366デフォルトの名無しさんNGNG
>>364
引数の書き方がわからないです。教えてくらはい。
0367デフォルトの名無しさんNGNG
>>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.
0368デフォルトの名無しさんNGNG
>>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;
}
0369デフォルトの名無しさんNGNG
363、366です。
わかりました!!
これで明日のミーティングに間に合いそうです。
みなさんありがとうございました。
0370デフォルトの名無しさんNGNG
C++のSTLには、叙述関数と関数オブジェクトの2種類があって、互いに
よく似ているために未だに混同します。

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

皆さんはどうやって区別していますか?
■ このスレッドは過去ログ倉庫に格納されています