トップページ⇒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 あたりに。
0643デフォルトの名無しさんNGNG
>>642
なんでそのコンパイラの出力をはぶきやがるんだ?
0644デフォルトの名無しさんNGNG
>>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
0645デフォルトの名無しさんNGNG
>>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.

・・・ってなワケだ。あとは好きなように対処しな。
0646デフォルトの名無しさんNGNG
>>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;
}
0647636NGNG
>>637
なはは…うっかり忘れてました。
その間についに VC++ に別れを告げる決意を固めて、試したのは g++ 上でした。

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

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

Hoge<int> hoge;

で Hoge<int>::Hoge() と表示してほしいんですが・・・
0650デフォルトの名無しさんNGNG
>>649
typeid(T).name()
0651デフォルトの名無しさんNGNG
>>649
typeid(T).name()
0652651NGNG
>>650
ケコーン
0653デフォルトの名無しさんNGNG
それはconst char*でして、文字列リテラルではないかと・・・
コンパイル時に Hoge<int>::Hoge になって欲しいんです・・・
0654デフォルトの名無しさんNGNG
>>653
無理。
std::string でも使え。
0655デフォルトの名無しさんNGNG
ガビーン
あきらめます・・・
0656 NGNG

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

{
    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 );
}
0657デフォルトの名無しさんNGNG
>>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);
0658デフォルトの名無しさんNGNG
これでもいい。
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);
0659デフォルトの名無しさんNGNG
文字列が"abd>efg<hijklmn"とかだと破綻しねぇか? 全部。
0660デフォルトの名無しさんNGNG
>>659
エラーチェックしてないから。したらしたなりになる。
0661デフォルトの名無しさんNGNG
>>656
boost::regex使えばいいのに。
0662656NGNG
正規表現で探すのは後に実装する予定でした。
とりあえず抽出だけを考えてます
それで、関数を作ってみました。

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;
}
0663656NGNG
使用してみました

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 初心者なもので、色々と不具合があるかもしれません。
みなさんどうもありがとうございました
0664デフォルトの名無しさんNGNG
>>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);
}
0665デフォルトの名無しさんNGNG
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 ) );
}

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

ちなみにテンプレートクラスとして定義されているので、ユーザ定義クラスに対する
ハッシュ値は、自分で specialization しないと計算できない。
0671デフォルトの名無しさんNGNG
>>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);
}

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

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

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

std::copy(std::istream_iterator<char>(ifs), std::istream_iterator<char>(), std::ostream_iterator<char>(std::cout));
}
0674デフォルトの名無しさんNGNG
>>673
std::istream_iterator<type>(i)は、i >> t を内部で実行しているため、
ホワイトスペース文字はスキップされて読み込まれない。
0675デフォルトの名無しさんNGNG
>>674
ありがとうございます♪
意外でした。std::getlineか何かで読み込んでみることにします。
0676デフォルトの名無しさんNGNG
>>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));
}
0677デフォルトの名無しさんNGNG
> ifs >> std::noskipws;

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

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];
}
0680デフォルトの名無しさんNGNG
なるほどこれなら単純で良いね。

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

std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(), std::ostream_iterator<char>(std::cout));
}
0681デフォルトの名無しさんNGNG
STLportって何がいいの?ラインセンスもアレだし。
0682デフォルトの名無しさんNGNG
>>679
ちなみに某所ってどこよ?他にもお宝眠ってたりせんかの?
0683デフォルトの名無しさんNGNG
>>682
たぶん ttp://www.kmonos.net/wlog/23.php あたりか?
でもこれ自体は別に新しくもない話題だよ。
ttp://www.ganaware.org/D/diary/2000-07.html
0684679NGNG
>>682
tp://www.issei.org/diary/ にて。
>>683
そーだったのか…
0685682NGNG
>>684
なるほろthx!
>>683
まぁまぁそう言わんと。知らん人間にとっては新しくなくても十分面白かったんで。
0686デフォルトの名無しさんNGNG
>>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);
}
0687デフォルトの名無しさんNGNG
lokiのSmartPtrを使ってるひとはいますか?
あれがもっとも汎用的でいいと思うのですが
なんでboostには含まれないのかな?
0688デフォルトの名無しさんNGNG
>>687
つかってまつ。gcc 2,95のバグに悩まされました。
0689デフォルトの名無しさんNGNG
>>687
いま、ちょうどboostのMLでLokiの人含めて色々議論してるようだから読んでみれば?
0690デフォルトの名無しさんNGNG
>>687
boost-mlでなんか今 auto_ptr みたいな挙動をどーするか
議論してるよ。boostに取り込まれる予定なはず。いつかは知らんけど。
0691690NGNG
ぐはぁ、かぶった。逝ってきまふ・・・
0692デフォルトの名無しさんNGNG
>>691
逝かんで良いから、議論の流れをザクッと要約してくれると嬉しい。
0693690NGNG
>>692
無理でふ。サラッと見ながら
「あー、なんかモメてるっぽいなぁ」
程度にしか読んでいないので・・・
「結論出たら結論だけ見ればいいや」
と思ってるんであんま(全然)流れ追ってないんですわ。

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

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

Generic Programming あたりを読んでお勉強するのが良いと思われ。
0716デフォルトの名無しさんNGNG
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;
}
0717デフォルトの名無しさんNGNG
>>716
BCC5.6.2だとちゃんとSpecialになるよ。
0718デフォルトの名無しさんNGNG
>>717
お、そうですか・・・。BCC5.5のバグなんですね。ありがとうございます。
0719デフォルトの名無しさんNGNG

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

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

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


0720デフォルトの名無しさんNGNG
>>719

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

>>723
中の人な(ry
0725722NGNG
>>723
通じるなら立派なネタじゃないか
0726デフォルトの名無しさんNGNG
ザクの犯人はシャア
0727デフォルトの名無しさんNGNG
templateの型推測のアルゴリズムが今ひとつわかりにくかったので
良書を探していたら、C++Primerが目に止まった。

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

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

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

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

いろいろ考えましたが思いつきませんでした・・・
0735デフォルトの名無しさんNGNG
>>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; }
0736デフォルトの名無しさんNGNG
>>729
http://www.damtp.cam.ac.uk/user/kp229/tree/

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

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

の時にa1、a2に[]を使ってアクセスする方法はないでしょうか?
0738デフォルトの名無しさんNGNG
#define private public
0739738NGNG
あ、違った。失礼。
まぁ、operator[]でも定義しなさいってこった。
0740737NGNG
A1,A2,・・・がA_Baseから派生していて、a1,a2が配列要素になっていたら
[ ]を定義できるのですが、この場合どうやったらいいか分かりません。
また上記の場合派生して加えた関数にアクセス出来ません。templateを使って旨く出来ないでしょうか?
0741738NGNG
ん?
B::operator[]
をテキトーに定義してやるんじゃマズいの?
なんか良く意味が分かんないんだけど。
0742デフォルトの名無しさんNGNG
>>737
B b; があって、
b[0]がa1、b[1]がa2を返すとか、そういう事かい?
■ このスレッドは過去ログ倉庫に格納されています