【C++】template 統合スレ -- Part6
>>1 _n
( l _、_
\ \ ( <_,` )
ヽ___ ̄ ̄ ) グッジョブ!!
/ /
C++相談室に統一すれば良かったのに.....
ここを相談室と統一するのはどうかと思うけどな。
STLスレとBOOSTスレとこのスレを統合すべきだよね。
いやC++相談室とこことSTLスレが統合して(つまり標準)
BOOSTを分けるべきじゃ?
個人的には上のは全部一つのスレでいいとは思うんだけど
おっとここは標準じゃないんだったか
BOOSTはSTLの拡張みたいなものだから同じスレで良いと思う。
そもそもBOOSTなんてただの一ライブラリに過ぎないのにスレをわける必要があるの
だろうか。
MFCやATLでスレたってるじゃん
BOOSTはSTLの拡張みたいなものだから
BOOSTはSTLの拡張みたいなものだから
BOOSTはSTLの拡張みたいなものだから
BOOSTはSTLの拡張みたいなものだから
BOOSTはSTLの拡張みたいなものだから
BOOSTはSTLの拡張みたいなものだから
BOOSTはSTLの拡張みたいなものだから
BOOSTはSTLの拡張みたいなものだから
BOOSTはSTLの拡張みたいなものだから
1には申し訳ないが
ここと【C++】STL(Standard Template Library)相談室はもういらんだろう
以後は話題によって如何に書くべし
BOOSTを語れゴラァ
C++相談室 part37
【初心者歓迎】C/C++室 Ver.12【環境依存OK】
C++スレで質問する初心者はだいたい標準C++及びSTLでの回答を期待してると思うんだ。
だからこれらは一緒にしてもいいと思う。
以前はLokiとかも考慮してここが立ってたのにな。
前みたいにスレタイにBoostやLokiを入れてれば重複スレに置き換わられることも無かったろうに。
Lokiに限定した質問て最近ほとんどないので現状では
BOOSTを語れゴラァ
C++相談室 part37
どっちかに振れば良いと思う
「BOOSTを語れゴラァ」の次スレあたりで
Lokiの名前を加えるといいのではないでしょうか
AssocVectorについて
20 :
デフォルトの名無しさん:04/11/26 21:15:20
Loki って使いものになります?業務で。
>「BOOSTを語れゴラァ」の次スレあたりで
>Lokiの名前を加えるといいのではないでしょうか
それはつまり内容的にここのことじゃないか。
標準C++相談室【STL含む】スレと
C++テンプレート相談室【Boost/Loki】スレ
があればいいんだ。
これでスレタイで検索できるから重複も立たないし、
質問する人もわかりやすい。
24 :
デフォルトの名無しさん:04/11/26 21:24:24
>>22 いいですね
C++相談室は今のスレが950くらいになったら
次スレの名前として「標準C++相談室【STL含む】」を提案しましょう
で「C++テンプレート相談室【Boost/Loki】スレ」はどうします?
boostってそもそもtemplateじゃないのも多いのに
>>25 別にC++非標準ライブラリ相談室でもいいぞ
>>20 実際の開発で Loki 使っている人いる?是非聞きたいなー。
crypto++とかについて話せるスレがやっとできるのか
lib*のC++インターフェースが用意されてない事も多いから
C/C++非標準ライブラリ相談室にしよう。
C/C++非標準ライブラリ相談室【Boost/Lokiなど】
とライブラリ名を入れるのを忘れないようにしよう。
入れないと絶対重複スレ立てる人いるから。
C++アブノーマル相談室
>>31 「C/C++非標準ライブラリ」というと標準以外全部含みそうなので(まぁBoost/Lokiなどといれてるけど)
C/C++環境非依存ライブラリ相談室【Boost/Lokiなど】
C/C++准標準ライブラリ相談室【Boost/Lokiなど】
とかどうでしょうか?
>>33 標準以外全部含んでいいんじゃないの?
専用スレがあったら誘導すればいいんだし。
そのスレタイだと初心者が迷いそう。
そもそもスレタイは初心者が迷わないために工夫するんだし。
>>34 >そもそもスレタイは初心者が迷わないために工夫するんだし。
そうかもしれない
じゃ自案は取り下げて如何を支持します
C/C++非標準ライブラリ相談室【Boost/Lokiなど】
そうすると今後は純粋にtemplateについての質問は
標準スレに回ることになるんですよね?
そこらへんは「柔軟に」ってことで良いのかな?
標準スレだろ
もういまどきテンプレート関数やクラスをC++じゃないなんて
言う奴もいないだろ?
CとC++は分けたほうがいいと思うなぁ…
分けられるとlibpngをC++で使いたい時とか困るよなあ…
標準か非標準かよりも(比較的)汎用か非汎用かの方がスレを分ける際に重要だと思うけど。
MFCがC++スレに混ざってたら、大半の人にとっては無関係な話題が延々繰り返されるわけでうざくてしょうがないが、
boostもLokiもある程度の環境で使えるんだからみんな全く無関係ってほどでもないだろ?
MFCは専用スレが既にあるから問題無いと思うが
>>41 それってポータブルかどうかってことだと思うんだけど
訳は汎用でいいの
>>43 気にするな。いい日本語が思いつかなかっただけだ。
>>41 標準 / 非標準環境非依存 / 非標準環境依存 の3通りだな
...表記長いな
ところで
boost/algorithm/string/replace.hppの
//! Replace all algorithm
...
\return A reference to the modified input
*/
って間違いだよね?replace_allは戻り値voidだし。
コピペしたときに消し忘れたっぽいね。
むしろその方が使いやすいような気がするんだけどなぁ。俺が自分で
作って使っていたreplace_allは名前が同じで引数がまったく同じシグニチャで
戻り値だけが違って変更後の文字列への参照を返してた。
In place modificationはvoidを返すんでいいよ。
プロトタイプ見ただけでin placeであることが分かる。
あぁ、なるほど。そういう考え方の切り口があったのか。
アリガトン。
以下のコードをビルドするとリンカで外部参照未解決というエラーがでます
template<class T> T Test(T t){ return t; }
//template int Test<int>(int); //明示的に生成
int main(){
//Test<int>(0); //普通に使用
boost::bind(Test<int>, 1);
return 0;
}
どちらかのコメントをとると上手くいきますが、こういう仕様でしょうか?
捨てるしか
>>54 そうですか。2005まで粘ろうかなぁ。なんて。あははhっは
2005 までは Toolkit とか 2005 Beta とか 2005 Express 使ってりゃいいじゃん
VC6 はさっさと捨てろ
貧乏人は死ね
優越感に浸りたいお年頃
うちは金持ちだけど6.0
ダメじゃん。
62 :
デフォルトの名無しさん:04/12/09 01:13:37
下がりすぎage
template=天ぷらって?
10点ならいいじゃん。
オリンピックだって10点満点で評価してるしな。
違う。1000点満点中の10点だ。よく覚えとけ。
boostの質問はここでいいのでしょうか?
以下のようにboost::bindを二重に使うと上手くキャストできません。
二回目のBase&を渡すところで内部でコピーされてスライスされているのでしょうか。
ポインタで渡せば問題ないのですが、参照で保持してくれるようにはできませんか?
struct Base { virtual ~Base() {} };
struct Hoge : public Base { };
void bar ( Base& b ){
if ( Hoge *p = dynamic_cast<Hoge*>(&b) )
std::cout << "bar ok" ; //ここへはこない
}
void foo ( Base& b ){
if ( Hoge *p = dynamic_cast<Hoge*>(&b) )
std::cout << "foo ok" ;
boost::bind ( &bar, b )();
}
int main(){
Hoge hoge;
boost::bind ( &foo, hoge )();
return 0;
}
boost::bind ( &foo, boost::ref( hoge ) )();
間違えた
-boost::bind ( &bar, b )();
+boost::bind ( &bar, boost::ref ( b ) )();
-boost::bind ( &foo, hoge )();
+boost::bind ( &foo, boost::ref ( hoge ) )();
ね
bindが引数の型を推論するときにBase &のtop-level referenceを剥いじゃうんですよね・・・
>>69 67の例だとhogeをラップする必要はないですよ.
即答ありがとうございます。上手くキャストされました
listのメンバであるsort関数についてお尋ねしたいのですが、
これの引数であるCompare compというのはどういう物なのでしょうか。
関数オブジェクトやfunctionalの物かと思って色々試してみたのですが、どうにも上手くいきません。
普通に二項の関数オブジェクト
すいません、functionalでもgreaterだけは通りました。
lessやless_equal、greater_equalでは駄目みたいです。
>>74 レスありがとうございます。では私の何かやり方がまずいっぽいです。
どうか添削して頂けないでしょうか。
#include <iostream>
#include <list>
using namespace std;
struct func_object{
bool operator()( const int& lhs, const int& rhs ){
return lhs < rhs;
}
};
int main(){
list<int> list_hage;
list_hage.push_back( 5 );
list_hage.push_back( 1 );
list_hage.push_back( 3 );
list_hage.sort( func_object() ); //error: struct func_objectから、struct std::greater<int>に変換できません(VC6)
//確認用
for( list<int>::iterator it = list_hage.begin(); it != list_hage.end(); ++it ){ cout << (*it) << endl; }
return 0;
}
>>75 コンパイラがまずいんじゃないの?gcc3.4.2では普通に通るぞ。
#include <iostream>
#include <list>
struct func_object {
bool operator()(const int& lhs, const int& rhs) const {
return lhs < rhs;
}
};
int main()
{
std::list<int> list_hage;
list_hage.push_back(5);
list_hage.push_back(1);
list_hage.push_back(3);
list_hage.sort(func_object());
//確認用
for (std::list<int>::const_iterator it = list_hage.begin(); it != list_hage.end(); ++it)
std::cout << *it << std::endl;
}
77 :
うすげ:04/12/12 15:43:16
hogeの代わりにhageを使うヤツは嫌い。
だからVC6じゃC++は使えないんだって何度言えば
>>76 確認ありがとうございます。おかげですっきりしました。
勉強中の身ですし、頭からコンパイラのせいだ!とは言いづらく…。
>>77 私も眉毛と生え際の間がフォーフィンガーでして、自嘲の意味で良く使うのですが、配慮が足りずすいません。
>>うすげ
気にするな
個性だ
こんどからusageの替わりにusugeを使おう。
偉大なるstroustrupに敬意を示すため
我々C++プログラマは、むしろ積極的にhageを使っていくべきじゃなかろうか
むしろ積極的にトリップにBjarneを入れていくべきではないだろうか。
つまり
VC++6使ってる奴は貧乏人
っていうことですよ
決して割れに手を出さない分、高貴とも言える
金が無いならvc2005 betaでも使えば良いだろ。
金が無いならVCTKでも使えば良いだろ。
金がないならハンドコンパイルすればよいだろ。
90 :
デフォルトの名無しさん:04/12/17 11:45:57
Boost.Spirit見てて思ったんだが、
同じようにSQLクエリをC++で記述できないもんかな。
sql.select( Person.name, Person.sex ).from( Person ).where( Person.age>=20 );
ってな感じで。
>>90 今作ってるオリジナル言語のコンパイラが完成したら
開発に着手する気でいたw
95 :
デフォルトの名無しさん:04/12/25 14:39:04
T1 と T2 が整数型という前提で sizeof(T1) > sizeof(T2) の時に
T2型の整数をゼロ拡張してT1型の整数に変換するテンプレート関数
はどのように書けばよいでしょうか?
template<class T1, class T2>
T1 zero_ext( const T2& x );
ゼロ拡張?
意味不明。
俺用語を使うな。
>>95 template<class T1, class T2>
T1 zero_ext(const T2& x)
{
return static_cast<unsigned T1>(x);
}
ISO C++の4.7.2にあるunsignedのintegral conversionの事でしょうね。
zero expansionってのはアセンブラの世界では良く使うね。
>>97 それだと、T2が符号付きのときに符号拡張されちゃうんじゃないか?
じゃあこうか?
template<class T1, class T2>
T1 zero_ext(const T2& x)
{
return static_cast<unsigned T1>(static_cast<unsigned T2>(x));
}
そもそもunsigned T1とかできるのかな?
よく知らんが、boost::numeric_convertionってそういう目的のライブラリじゃないのかな?
104 :
デフォルトの名無しさん:04/12/25 19:10:36
template<typename T, typename Container = std::map<Key, T>, typename Key = std::size_t> class Tree { };
こういう順番にテンプレート引数を取りたいのですが、どうしたらいいでしょうか?
Tree<int, std::vector<T> >としたときKeyは当然不要なので省略できるようにしたいのです。
テンプレートのデフォルト引数は一つまでだYO
無理じゃね?
Tree<std::vector<int> > としたときTは当然不要なので
struct use_default{};
template <typename T, typename Container = use_default, typename Key = use_default>
class Tree{/* がんばって情報を取り出す */};
boost::iterator_adapterの実装が参考になるかも試練。
おまえらぶーすとに踊らされすぎだぶー
boostは一緒に踊ってくれる数少ない仲間なんだよ。
踊る阿呆に見る阿呆、同じ阿呆なら踊らにゃソンソン
踊らにゃシャンソン
>>111 必ずどちらかの阿呆であるという無理な前提で人を煽るその言葉は大嫌いだ。
2択でもなく決め付けだしな
詭弁だ
なんで踊るよりも見る方が損なのかがわからん。
踊ったら疲れるだけなのに。
理論(見る)より実践(踊れ)てこと
118 :
デフォルトの名無しさん:04/12/25 23:20:36
>>101 VC++ 7.1 だと unsigned T1 のような書き方は構文エラーになりました。
C++Templateの便利な機能のうち
Javaでは実現できないことってなんなのかを
教えてください。
特殊化
ていうかほぼ全部?
>>119 使ってすぐ分かるのは、コンテナから取り出すときにナローイング変換しなくていいこと。
あれ?
Java Genericsかと思ったけど、Javaか…
JavaのGenericsってただの自動キャストでそ?
C++のtemplateとは比較にならないのでは・・・
.NETのgenerics、試みは面白い。
126 :
デフォルトの名無しさん:04/12/26 13:31:14
で、結局具体的にどんなことがJavaにできなくて
C++で出切るんですか?
C++ではこんなに簡単に書けるのに
Javaで書くとこんな風になっちゃうって例を
出していただけると助かります。
いろいろ考えたんですが、特別優れた使い方ってのが
思いつかなかったので。
もしかして、ないのかな・・・
クマー
.| | | | | | | |
.| | | レ | | | |
∩___∩ | | | J | | |
| ノ\ ,_ ヽ .| レ | | レ|
/ ●゛ ● | .J し | |
| ∪ ( _●_) ミ .| し
彡、 |∪| | .J
/ ∩ノ ⊃ ヽ
( \ / _ノ | |
\ " / | | Javaしらね。覚える気もねえし
\ / ̄ ̄ ̄ /
>>126 Java Genericsは分かるの?
>>126 「オブジェクト指向をベース」にプログラムを書いた場合
JavaのGenericsで全てが事足りる。
速度以外はな。
素人が首突っ込んで申し訳ないが
Javaには専用プラットフォーム必須なんだよね?
要はエミュレータ?
>>132 プラットフォームの意味わかってんのか?
>>126 Lokiのような変態的なライブラリは無理じゃないの?Generics知らんけど。
その変態なLokiなんですけど、TYPELISTって動作遅くしないですか?
継承によって、多義性をサポートさせるのはよい。
コンパイル時にその多義性を作り出すのも良い。
けど、継承って、実行速度おそくなりませんか?
>>134 あれはオブジェクト指向を捨ててるからな。
オブジェクト指向で書き直せばもっときれいなのが作れるよ。
>>135 Modern C++ Designを読めば分かるけど、
LokiのPolicyは仮想関数を使ってないから…
>>135 TYPELISTはコンパイル時のみ。
継承なしで巨大ライブラリを作れる人、使える人はそうしたら良かろう。
Cで書いてあるgtk+みたいなのでも継承しているけどね。
大抵は問題にならん
lokiはデザパタではなくてboost::mplに似ているわけか。
たくさんのレスに感謝。
>137
Modernは読んでます。内容を完全に理解したとは言いがたいですが。
けれども、Efficient読んでるとvirtual使わない継承でも動作遅くなるよ〜。
と書いてあるもので。
「本質的な問題ではない。」が結論なんですけどね。
>138
その通りです。
継承無しでライブラリの作成…作ったことありませんがゾッとします。
>139
>大抵は問題にならん。
継承しまくったオブジェクトを生成&削除しまくるプロジェクトとか
(サーバー用途?)ではどうでしょうか?
ModernのTYPELISTの継承構造見ていると、継承の無駄が多い気がして。
p237のクラス階層とかってつまりは。
class AbstractEnemyFactory :public AbstractFactoryUnit<Soldier>,
public AbstractFactoryUnit<Monster>, public AbstractFactoryUnit<SuperMonster>
なわけで。
実際に巨大プロジェクトの現場を経験したことのない人間の戯言ですが。
>実際に巨大プロジェクトの現場を経験したことのない人間の戯言ですが。
自覚しているんなら黙れ。っーつか氏ね。
>っーつか氏ね。
OK。発音してみよう。
>>141 それ、TYPELISTなしで書いた方が可読性悪いでしょ。
TYPELISTは実行時に負担ないしね。コンパイル時にやるから。
typeid listじゃないから。
>継承しまくったオブジェクトを生成&削除しまくるプロジェクトとか
>(サーバー用途?)ではどうでしょうか?
メモリ確保&解放は一瞬。メモリに書き込むことは多少重いけど。
ただ、ゲームなんかのメモリ資源が超少ない環境では
メモリのフラグメントなんかが起こって、メモリが足りなくなることはある。
いや、new/deleteは重いけど、
継承しているしていないに関係ない。
継承して複雑な部分を作り出す構造だと、
一つのオブジェクトの中にまとめられるから、
利用するメモリチャンクの数が減ることも考えられる。
Cでやると、ポインタの嵐になって別々の構造体になるから、
malloc/freeを寄り頻繁にする必要がある(事が多い)。
とりあえず、135は、
・templeteが、compile時のみ働くものであること
・詳解C++(いわゆるAnnotated)を読んで、継承のメモリ利用
を勉強しろ。
分からない奴はいつまでたっても設計ができない。
>>148 > Cでやると、
「継承しないでやると、」の方がいいかな。
compositionとinheritanceの違いはAnnotated読んで。
みんなRubyのこと嫌いなの?
自分でTYPELISTでAbstractFactoryを組んで、それをいじくりまわしてみました。
結果:変わらないですね…
なんか狐につままれた感じのするのは私だけでしょうか。
>・詳解C++(いわゆるAnnotated)を読んで、継承のメモリ利用
を勉強しろ
多分これが今の私に必要なんでしょうね。
はい。いろいろとがんばってみます。
皆様ありがとうございました。
>結果:変わらないですね…
コンパイル時間が変わっていると思うけど……
153 :
デフォルトの名無しさん:04/12/29 01:08:18
mmap+boost で、データ構造のシリアライズがやりたいです。
具体的には、
1、データファイルをmmap で巨大なヒープとしてメモリに貼り付ける。
なお、このとき、毎回同じメモリアドレスに貼り付ける必要性がある。
2、boost の new をいじくり、すべてそのmmapされたヒープの中でのみ
allocate されるようにする。
以上で、データ構造がそっくりシリアライズできるような気がするのですが、
どうやってやればいいでしょうか。
boost::serialize使えばいいのに
boost::serializationだった
156 :
デフォルトの名無しさん:04/12/29 03:49:42
ええっと、それだと、一度すべての変数をずるずるっと舐めることになりますよね。
そうじゃなく、効率も考え、変数空間全体をmmap でファイルに貼り付けたいんです。
舐めるならレロレロとかチュパチュパじゃないか?
ずるずるってナニ?
つーか
>毎回同じメモリアドレスに貼り付ける必要性がある。
これで破綻してるとは思わないのか
159 :
デフォルトの名無しさん:04/12/29 05:06:16
それはすくなくともLinuxなら可能です。
とくに、今後の64bit Linuxなら、アドレス「空間」はいくらでも余ってるので、
何の問題もないでしょう。
>>153 やりたいようにやればあ。
絶対アドレス依存じゃないヒープ保存で有名なのはEmacsとTeX。
絶対アドレスに依存するのはちょっと面倒だね。
C++のオブジェクトを直接張り付けるんじゃなくても、
wrapper classで仮想的に扱えるよね。
おまえら、「boost の new」の意味はわかってるのか?
漏れにはわからん。
「boostで使うnewとかもひっくるめて自分でglobalなoperator new()をオーバーライドしちゃいます」
という意味だと思ってた
>>163 そうなると、「mmap+boost で」っていうのがわからん。
boost も template も関係ないじゃないか。
ううむ。確かに。
boostの機能のキの字も使ってないもんなぁ。
そもそもシリアライズじゃないし(w
知り合いs
GC(参照カウント方式)に使えるポインタオブジェクトで
オブジェクトのconst修飾が参照先のconst修飾に対応した
クラスってないでしょうか
Boost流だとこんな↓感じ?
template<typename T>
class my_shared_ptr : protected boost::shared_ptr<T>
{
public:
const T * operator->() const { return __super::operator->(); }
T * operator->() { return __super::operator->(); }
// other functions implementation...
};
おねがいします
はい、ありがとうございます
ただ、既存のライブラリでいいのはないかと思いまして・・・
>>170 Boost は「既存のライブラリ」以外の何だというのかね?
>>168 ちなみにshared_ptr<T const>を嫌う理由は何ですか?
重い
プログラム全体の動作に致命的なほど遅くはなんねぇよ
何の要件もなしに「重い」と言って切り捨てる >173 も、
何の前提もなしに「致命的なほど遅くはなんねぇ」という >174 も、
同じ程度に浅はかである。
>>175 それを否定してしまったら何もかけなくなっちゃうよ。
日本の将来
俺も人格も否定しているような気がする。
>>172 嫌というほどでもないんですが、
コンパイルが遅そうとか、その程度です
const my_shared_ptr<T> get_obj_ptr() const;
my_shared_ptr<T> get_obj_ptr();
より、
shared_ptr<T const> get_obj_ptr() const;
shared_ptr<T> get_obj_ptr();
の方が意味的に適切だとは思うんですが
自分で書くのめんどうなので、とりあえずboost::shared_ptrでいいや・・・
こういうのどうですか?
#defineBEGIN_JUNK( __Super, __Misc ) \
template< int _N >struct __Junkyard{ enum { _junk_no = __Junkyard< _N - 1 >::_junk_no }; }; \
template<> \
struct __Junkyard< __LINE__ > : public __Super::_junk \
{ \
enum { _junk_no = __LINE__ }; \
typedef __Super::_junk _prev; \
__Misc; \
}; \
typedef__Junkyard< __LINE__ >_start_junk; \
#defineREDEF_JUNK( __Misc ) \
template<> \
struct __Junkyard< __LINE__ > : public _prev_junk \
{ \
enum { _junk_no = __LINE__ }; \
typedef _prev_junk_prev; \
__Misc; \
}; \
#defineEND_JUNK() \
typedef_cur_junk_junk; \
長いので詳細は↓に書いてあります。
http://www2.odn.ne.jp/freelife/Junkyard.htm 割と使えると思うんだがどうだろう?
>181
マクロで実装してるreflection系ライブラリの提案見るたびに思うんですけれど
マクロとテンプレートの相性の悪さはどう対処するつもりなんでしょうか?
毎回typedef?(面倒)BOOST_PP_SEQ?(カッコ悪い)variadic macro待ち?(いつ出る?)
struct Sample2
{
typedef Sample2 _self;
BEGIN_JUNK( ZJunkBase, typedef ZTypeList<> _data_member1; );
DATA_MEMBER( 1, my_class<char, int>, x );
END_JUNK();
};
>>182 言いたいことには同意
対処って程ではないが、苦肉の策でこんなことやってる
#define $ ,
struct Sample2
{
typedef Sample2 _self;
BEGIN_JUNK( ZJunkBase, typedef ZTypeList<> _data_member1; );
DATA_MEMBER( 1, my_class<char $ int>, x );
END_JUNK();
};
はげしくかっこ悪いが w
>183
それだとDATA_MEMBERが評価される前に$が評価されてしまうので結局同じことになりませんか?
色々漁ってみたら限界はあるもののいくつか対処法はあるみたいですね.
http://lists.boost.org/MailArchives/boost/msg46364.phpからだと template<class T> struct wrap { typedef T type; };
template<class T> struct wrap<void (T)> { typedef T type; };
#define TYPE(x) wrap<void x>::type
#define DEP_TYPE(x) typename wrap<void x>::type
struct Sample2
{
typedef Sample2 _self;
BEGIN_JUNK( ZJunkBase, typedef ZTypeList<> _data_member1; );
DATA_MEMBER( 1, TYPE((my_class<char, int>)), x );
END_JUNK();
};
とか.記事本文では指摘されていないですけれど,型がdependent typeか
どうかでマクロを使い分ける必要もありますね,これ.
・・・っていうか話題をそらしてしまってすいませんです.
>>184 コンパイル通らないですか?
当方、VC++ 2003 しかないので、他のコンパイラだと通らないのだったら正直すまん
ただ、VC++ 2003 でも多重にマクロを定義している時は、評価順序によって通らない時もある
その時はマクロを調整するでは駄目ですか・・?
リンク先のようなやり方もあるとは知りませんでした
参考にさせて頂きます
あと、typename に対してですが
__if_exists が使えればこういうやり方もあります
template< bool >struct ExistsBool {};
template<>struct ExistsBool< true > { enum { _true }; };
#defineTYPEDEF( __Type, __Alias ) \
__if_exists( __template__::_true ){ \
typedef typename __Type __Alias; \
} \
__if_not_exists( __template__::_true ){ \
typedef __Type __Alias; \
} \
template< class _Type >
struct Sample7
{
typedef ExistsBool< true >__template__;
TYPEDEF( _Type::_type, _type );
// 2値判定にも使える
__if_exists( ::ExistsBool< _Type::_n == 0 >::_true ){
}
};
__template__ をクラスごとに宣言する必要があるのが難点ですが
>>184 >それだとDATA_MEMBERが評価される前に$が評価されてしまうので結局同じことになりませんか?
引数展開の前に引数は確定するから、この例では問題ない。
でもこの結果を別のマクロに渡すと結局だめだから、
あまりお勧めはできないが。
# define ID(x) x
# define COMMA() ,
# define DECL_A(type, var) type var
# define DECL_B(type, var) ID(type) var
DECL_A(std::pair<int COMMA() int>, pa); // ok
DECL_B(std::pair<int COMMA() int>, pb); // error: IDの引数過多
>186
考えてみた結果enclosing scopeがtemplateかどうかに対する切り分けが
本質的に必要ではないかと思うのでこの方法はあまり使えなさそうです.
>187
マクロのargument substitutionについて理解が足りていませんでした.
function-like macroがidentityされてから後,replacement-listに対する
置換が実行される前にargumentに含まれるmacro tokenが置換されるんですね.
見た感じやはり184の解法が幾分かbetterでしょうか.
これでどうだろう。
>>184 と組み合わせてみた。
template<class T> struct wrap{ typedef T type; };
template<class T> struct wrap<void (T)>{ typedef T type; };
#define TYPE(x) wrap<void x>::type
template< bool >struct ExistsBool{};
template<>struct ExistsBool< true >{ enum { _true }; };
#defineTYPEDEF( type, alias ) \
__if_exists( __template__::_true ){ typedef typename TYPE((typename type)) alias; } \
__if_not_exists( __template__::_true ){ typedef TYPE((type)) alias; } \
#defineCLASS( __Class ) \
typedef __Classself; \
typedef ExistsBool< false >__template__; \
#defineTEMPLATE( __Class ) \
typedef __Classself; \
typedef ExistsBool< true >__template__; \
#define$,
つづき
template< class T >
struct hara
{
TEMPLATE( hara );
template< class T > struct horo
{
TEMPLATE( horo );
TYPEDEF( T::type,type );
};
struct hire : public horo< T >
{
CLASS( hire );
TYPEDEF( my_class<char $ int>, type2 );
};
TYPEDEF( hire::type, type );
TYPEDEF( hire::type2, type2 );
};
$ を主張するわけではないが、タイプ量が少ないと嬉しいので
ところで、誰も Jankyard に触れてくれない orz
誤: typedef __Classself;
正: typedef __Class self;
誤: #define$,
正: #define $ ,
です。連投すんまそん
>>192 今回提案したのはリフレクション自体ではなく、その辺りをサポートする仕組みだったのだが。
リフレクションも含む、その他タイプリスト生成や、マクロ間での型の受け渡し、
継承関係の中で連番発行など。プロパティはネタです。
__if_exists は本質的に必要ないのには同意します。
ただ、テンプレートの特化の変わりに使えるので
__if_exists を使うとシンプルに記述出来ることも少なくありません。
この辺りは好みによるのでしょうね。
VC++限定なのはどうしようもないですが。
いづれにせよ、騒がしているだけのようなので、これで引っ込むことにします。
>一応クラスのメンバ(型・関数・変数)や非メンバ関数の存在をテストしてその情報を
>コンパイル時に取得する技法を標準C++の範囲内で実装することは可能なので,
>それでほとんどの部分は代用できると思います.
詳細きぼん
194 :
デフォルトの名無しさん:05/01/09 12:47:08
ここでいいのかしら。ちょっと彷徨い気味ですがどうぞよろしゅう
2つのソート済みvectorの中で共通する項目の数を数えたいのですが
set_intersection( (省略) , common_ins)
common.size();
で実行しています。これだとvectorの中身が100kとかになった時に速度がちょっとまずいのです。
上記より高速な方法でなにか良案ご存知の方いらっしゃいませんか?
ちなみのその後、共通部分から作ったcommonに対する処理は何も行いません(数えたいだけです)
vecAとvecBを
mergeしてvecCを作りuniqueしてvecA.size()+vecB.size()-vecC.size()
set_intersectionもソート済み範囲なのか。なら
>>194の方が遅そうだ。
mergeして差分を考える方法は実行済みなのですが
残念ながら、set_intersectionの方法に比べて倍近く時間がかかってしまったのです
う〜ん、これはもう構造的にどうしようもないですかね
割と頻繁に更新されるvectorなので、馬鹿にならないコストなんですが・・・
スマートポインタを使ってるならただのポインタに変えてみる。
ただのポインタなら実体に変えてみる。
実体ならポインタに変えてみる。
set_intersection の result は OutputIterator なので、
*result = common (or *result++ = common)
がカウントアップの動作をするような擬似イテレータを作れば、
コピーのコストを無くすことができそうだ。
うっ、そこを触ることになりますか…
Iteratorの中身について理解が出来ていないので全くの手探りになりますが、資料ひっくり返して勉強します
ありがとうございました
暇つぶしにやってみた。
boost::counting_iterator がそのまま使えるかと思ったけど OutputIterator じゃなかった。
しょうがないから結局ファンクタ書く羽目になった。
#include <cstddef>
#include <algorithm>
#include "boost/function_output_iterator.hpp"
template<typename Incrementable>
class increment
{
Incrementable* m_target; // not reference to make this class Assignable
public:
increment(Incrementable& target) : m_target(&target) {}
template<typename T> void operator () (T const&) { ++*m_target; }
};
template<typename InputIterator1, typename InputIterator2>
std::size_t count_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
{
std::size_t result = 0;
std::set_intersection(first1, last1, first2, last2
, boost::make_function_output_iterator(increment<std::size_t>(result)));
return result;
}
lambda 使えば、 increment くらい消せるかも。
いちおうできた。
#include <cstddef>
#include <algorithm>
#include "boost/function_output_iterator.hpp"
#include "boost/lambda/lambda.hpp"
template<typename InputIterator1, typename InputIterator2>
std::size_t count_intersection(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
{
std::size_t result = 0;
std::set_intersection(first1, last1, first2, last2
, boost::make_function_output_iterator(++boost::lambda::var(result)));
return result;
}
ただ、 lambda のファンクタが Assignable にならないので、
_GLIBCXX_CONCEPT_CHECKS で怒られた。
VCでは /W3 まで大丈夫。
205 :
デフォルトの名無しさん:05/01/09 19:25:21
template<class T>
struct X {
void func() {}
};
TがクラスAかクラスAのpublic派生クラスの特殊版を定義する場合
X<T>::func()をどのように定義すればよいのでしょうか?
>193
具体的な実装の例だとboost/mpl/has_xxx.hppとかが参考になるかと思います.
>205
Boost使うなら以下のような感じでですかね?
#include <iostream>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
struct A{ };
template<class T> struct X{
struct yes_tag{ };
struct no_tag{ };
typedef typename boost::mpl::if_<
boost::is_base_and_derived<A, T>, yes_tag, no_tag>::type
dispatch_tag;
void func_dispatch(yes_tag){std::cout << "derived version" << std::endl;}
void func_dispatch(no_tag){std::cout << "non-derived version" << std::endl;}
void func(){ func_dispatch(dispatch_tag()); }
};
struct Hoge : public A{ };
struct Huga{ };
int main(){
X<Hoge>().func();
X<Huga>().func();
}
こういう書き方って動作は保証されるのでしょうか?
std::vector<int> test;
for ( std::vector<int>:iterator element = test.begin(); element != test.end(); element++ ) {
test.erase(element);
}
↑おもいっきりぬけてたので修正しました
std::vector<int> test;
test.push_back(0);
test.push_back(1);
test.push_back(2);
test.push_back(3);
test.push_back(4);
for ( std::vector<int>:iterator element = test.begin(); element != test.end(); element++ ) {
if ( *element == 2 ) {
test.erase(element);
}
}
>>208 eraseした時点でイテレータそのものが無効になるよ。
ではループしつつ条件に当てはまるイテレータの内容だけ削除するには
どのような手段を用いればよいのでしょうか?
プールで一端どこかにマークをつけて、ループ終了後該当の物だけeraseとかでしょうか?
だから、std::remove()で、値が2の要素をコンテナの後に集めておき、最後に一回だけ
eraseするといい。
test.erase(std::remove_if(test.begin(), test.end(), std::bind2nd(std::equal<int>(), 2)), test.end());
あ、ループがプールに・・orz
なるほど、ありがとうございます
こういう書き方は最初は戸惑うかもしれないが、慣れるとすごく便利になる。
そのうちこれでも不便になって、必ずboost::bindとかに手を出したくなるから。
わかりました。
参考にしてみます。
というか、EffectiveSTLを読め。
>>211のも含めて色々書いてあるから
test.erase(std::remove(test.begin(), test.end(), 2), test.end());
でもいいねこの場合。叙述関数あるいは関数オブジェクトの替わりにconstな値を
とるだけだから。
if ( *element == 2 ) {
test.erase(element++);
}
でOK。
>>218は忘れて。
for ( std::vector<int>:iterator element = test.begin(); element != test.end(); ) {
if ( *element == 2 ) {
element = test.erase(element);
}
else
++element;
}
>test.erase(std::remove_if(test.begin(), test.end(), std::bind2nd(std::equal<int>(), 2)), test.end());
わけがわかりません。
こんなの仕事で使われたら恐怖です。
やめてください。
>>218 vectorコンテナのeraseはCで言うところのrealloc()に相当する動作を実行する
事もあるんだぞ。でたらめ書くな。
>>220 そのくらいのSTL構文も分からないならC++使うのをやめた方がいいよ。
>>222 おいおい。
「イテレータは、より小さなインデックスの要素が挿入または削除されたり、再割り当てが
行われて容量が変わるまで有効」だぞ。
規格票をよく読め。おまえこそでたらめ。
規格票でました。
m9(^Д^)プギャー
§23.1.2.8当たりだろ。
>>226 それAssociative Container
ここは
問題を無闇に複雑にして悦に浸る馬鹿のス靴(なぜか変換できない)
ですね。
§23.2.4.3当たりだと見た。
boostが異常なのは認めなければなるまい。
昨今のC++は異常が常態。
確かに異常だが、使っているうちに快感になる。
(23.1.1/7)と(23.2.4.3/3)読む限り>219でもOKっぽいですね
CommonLispのようなわかりにくさを競い合って悦に浸るのがここの流儀
>>234 OKだろ。個人的には俺はあまり書きたくないけど。
237 :
デフォルトの名無しさん:05/01/11 00:57:13
>>219 引くってのはどうよ。
for(element = test.begin(); element != test.end(); ++it)
{
if(*element == 2){
test.erase(element--);
}
}
あ、でも element = test.begin(); element--; は大丈夫なのかな。
まぁ、EffectiveSTLを読んでいれば test.erase(remove(),test.end())と書くというのに一票。
238 :
237:05/01/11 00:58:59
訂正。
>>237 ++it => ++element
for(element = test.begin(); element != test.end(); ++element)
if(*element == 2)
{
element = --test.erase(element);
}
こんな感じが一番シンプルなところなのかな?
removeとeraseの組み合わせが一番シンプル
とりあえずremoveとeraseの組み合わせが何でも一番です(^^
clearって手もあるよ
>>223 プロジェクトって大抵いろんな技術レベルの人がいるから
その台詞でばっさりはちょっと抵抗あるなぁ。
一人でやるなら何使ったってOKだけどね。
>>244 211はかなり基本だと思うんだけど...
あれが解からないって?
…ときどき思うんだ。俺、なんで2chなんか見てるんだろう、って。
247 :
237:05/01/11 22:30:46
なんか不安になってきたので確認したいのですが
vectorのeraseで無効になるのは消した要素以降のイテレータですよね。
だから
>>237と
>>240は結果的に同じことになりますよね?
私が
>>237で心配だったのは
最初の要素でヒットしたとき、
element = test.begin();
--element;
++element;
でbegin()に戻るのが規格で保証されてなさそう(多くの実装では戻りそうだけど)
というのと
元々のサイズが1のとき、test.erase(test.begin());で全てのイテレータが無効になる
ときにバッファを解放してbegin()とend()がNULLを返してくるようになるとend()と
永遠に一致しなそう(VC7のclearがバッファを解放(capacityを0)にしてくれるのに
気づいて以来疑り深くなっています)
の二点なんですけど、
そのあたりをふまえて
>>239はダメと言っているんですよね?
うーん、remove(や類似のアルゴリズム)を使わないでやるならやはり
>>219なのか。
248 :
237:05/01/11 22:34:15
ああ、そうか、後者の不安は
>>240と書くことで払拭されるのか。
スマソ
>>245 俺も基本だと思ってるし、これぐらいわかれよって思ってるよ。
でも、それが通用しないのが多人数でしょ?って投げかけ。
…技術と関係なくなるか。消えるよ。スレ汚しすまん。
なぜforで回す……わざわざC++使うんだったら、効率にも気を
配らないともったいないよ。
>247
>237 >240の例だと
・ループごとにtest.end()の呼び出しが発生する
・elementを削除するたびにvectorの再パッケージが発生する
で遅くなりますな。
あと、>237だと後置インクリメントの一時オブジェクトの生成が
発生してさらに効率が悪くなります。
なぜにremoveを使いたくないのかが知りたい
自己フォロー
>237>240ともに、はelement==test.begin()のときに
*element==2だとアウトですな。
#test.begin()よりも前に移動するから未定義の世界に突入
>250
ループごとのtest.end()も後置インクリメントもここでは本質じゃない。
>253
ふうん、じゃ、こう言っておこうかな
・郷に入れば郷に従え
STLはC++の一部なんだから、それぐらい覚えろ
・こんぐらいできないなら、そもそもC++使うな
or こんなこともできないやつをプロジェクトに入れるな
他にもPerlとか色々あるんだから、わざわざC++を使う必要ないよね。
list に追加されている remove(),remove_if() 見習って、
template<class Container> void remove(Container&, typename Container::value_type const&)
template<class Container, class Predicate> void remove_if(Container&, Predicate p);
のような関数を作れば、双方文句はなかろう。
257 :
デフォルトの名無しさん:05/01/12 07:51:49
forで回すからうっかり
>>218とか
>>237とか
>>240とかいう問題のあるコードを書いて
しまうんだよ。
だったらおとなしくremoveを使えと。
まぁ、色々書き方があってその中から適切な物を状況に応じて選ぶのがプログラムの
醍醐味ではあるけど。
>なぜにremoveを使いたくないのかが知りたい
叙述関数やoperator==とかにコードが分散するのがイヤ
ループが内包されるのがイヤ ループを制御下に置いておきたい
ブレイクポイントが設定しやすいよ
削除以外の用途にループが流用できるよ
てゆうかぶっちゃけremove_copy中でやってること、あれはありえないでしょ
それを言ったらvectorでeraseすること自体ありえないかw
>ループが内包されるのがイヤ ループを制御下に置いておきたい
ループを明示的に書くより効率が良くなる可能性があるし、
コードの見通しも良くなる
260 :
デフォルトの名無しさん:05/01/12 10:06:05
>>254 「理想郷」との差でしかモノを語れない
頭でっかちの引き籠もりはレスしなくていいです ;-)
>260
それ、オレじゃない。人違いだ
262 :
デフォルトの名無しさん:05/01/12 10:48:33
>260
IDくらい見ろ、ボケ!
お前さんたちなんか楽しそうだね。
IDの見方知らない香具師ってまだいたんだね
はっきりいってvectorに限らず配列っぽいデータ構造を使っている時に
removeみたいなアルゴリズムを適用したくなることってあるか?
無理して適用しておもしろいことがあるようなものでもないと思うのだけど…
何か見落としている革新的な理由でもあったりするのだろうか?
> removeみたいなアルゴリズムを適用したくなることってあるか?
配列から複数の要素を一度に取り除きたいときだな。
簡単
let remove x num = snd (List.partition (fun a -> a=x) num);;
269 :
デフォルトの名無しさん:05/01/14 14:04:12
270 :
デフォルトの名無しさん:05/01/15 01:33:25
>>267 そそ、端からeraseしてると効率悪いし、
効率的な処理にしようとすると意外に面倒。
俺も小さくて、しかもあまり使わないような関数を分散させるのが嫌いなんだけど、
「リファクタリング」を読むと、一行処理すら場合によっては関数にすることを推奨してるんだよな。
しっかりした関数名をつけることによって可読性が高まるって話なんだけど、
必ずしもそうとは思えないのは、英語圏ネイティブじゃないせいかね。
と、templateスレに書き込もうとしたのだけど、主旨に合わないのでこっちに投棄
C++スレに書くつもりが…
もうどうでもいいや
リファ〜に書いてあるのは関数じゃなくてメソッドのことでは
何の分類もしない単独の関数増やしてくのはあんま良いとは思えないが
メソッドの場合インターフェース抽出とか階層整理とかで意味がある
>>273 失礼、つい関数と呼んじまう。
インターフェース抽出や階層整理は、それ自体をメインにして行うべきな気がするんだよねぇ。
それどころかそれ以前で、非道い話だが「たくさんの、たった数行のメソッド」ってだけで、嫌悪感を感じてしまう。
いずれにせよスレ違い申し訳ない。
>>273 そんな区別ないだろ。
少なくともC++ではthisポインタの有無しか違いはないわけで、
それが関数分けの基準に影響するとは思えない。
時々272のような人いるよね。
読むときあっちこっちの関数みないといけないから、とか言って。
このヘタレが
そもそも行数とか関係ないだろ
>275
その他にも可視性とアクセス範囲に違いがあるわけで……
>>278 そうだな。
それらが要るならクラス作ってメンバ関数を作ればいいし、
要らないならフリー関数にしてもいい。
どう整理するかどうかが違うだけで、
処理に名前をつけてまとめたほうがよいかどうかの基準には関係ない。
複数のフリー関数を作った後に、さらに
それらをまとめてクラスを作ればよいことに気付くことも考えられる。
思い立ったらさっさと名前付けてまとめれ。
渋る意味がわからん。
お聞きしたいのですが、
下記(次レス)のコードがVC7.1でコンパイルできませぬ。
どこがいけないのでしょうか…
色々実験してみた結果
・UINT を int にすると通る。
・UINT を std::size_t にしてもダメ。
・typename T を削除して、 boost::array の T を int とかにすると通る。
・boost:array の nSize を適当な数値で直打ちすると通る。
・bcc5.5.1 では普通に通る。
282 :
281:05/01/21 18:18:34
#include <boost/array.hpp>
typedef unsigned int UINT;
template<typename T, UINT nSize>
class A
{
typedef typename boost::array<T, nSize> tObjects;
typedef typename tObjects::iterator tObjectsIt;
tObjects m_cObjects;
public:
tObjectsIt Func();
};
// ↓C2244:関数の定義を既存の宣言と合致させることができませんでした。
template<typename T, UINT nSize>
inline typename A<T, nSize>::tObjectsIt A<T, nSize>::Func()
{
return m_cObjects.begin();
}
283 :
デフォルトの名無しさん:05/01/21 20:49:28
>>281 手元にVC7.1もboostもないし、よくわからんけど、
コンパイラがバグってることはよくあるからw
>>282 g++(3.3.3)ではなんの警告もエラーもなく通るのぅ……
>>282 戻り値を素直に
typename boost::array<T, nSize>::iterator
とすると通りますね。
typedefがprivateなのにinlineなのがいけないんじゃないのか?
と試してもないのに言ってみる
やはり、コンパイラが悪い方向なんですか… orz
なお、
>>286を参考に、
すべてのメンバをpublic にしてみてもコンパイルが通りませんでした。
しょうがないので、現状では
・class内に直書き
・
>>285 の方法
の2点で回避したいと思います。
どうもありがとうございました。
いまだにちゃんと動かないコンパイラ多いのかよ
おまえらC++信用できますか?
C++なら信用できるよ。
291 :
デフォルトの名無しさん:05/01/23 15:44:13
boost::bindはstd::bind2ndとかより実行速度が落ちるって本当ですか?
using句が,による複数引数を受け付けないのは何故ですか?
using A::AA, A::AB, A::AC;
のように出来たら便利だと思うのですが?
>>293 プリプロセッサマクロを書くとか?
あんまり便利とも思えないけど
297 :
デフォルトの名無しさん:05/01/23 22:42:53
boost(かSTL)に、次のような関数テンプレートって含まれていませんか?
template<typename T>
inline void assign(T& lhs, const T& rhs)
{
lhs = rhs;
}
次のような感じで、setterを用意していないメンバ変数(m_is_foo)を変更する関数オブジェクトを作るのに使いたいのです。標準であるならそっちを使いたいなと思いまして。
hoge(boost::bind(assign<bool>, boost::ref(m_is_foo), true));
>>297 試してないけど、 hoge(boost::lambda::var(m_is_foo) = true) じゃだめ?
>>298 > 試してないけど、 hoge(boost::lambda::var(m_is_foo) = true) じゃだめ?
いけました。サンクスです。
うーん、lambdaか…。主観ですが実戦投入はちょっと怖いんですよね。
ふぇ〜い
Boostを最新リリースにしたら@VC6
_bvector.hでコンパイラが内部エラー起こしてビルドできない
Releaseビルドなら通った
コンパイラもしょっちゅう固まるし
やっぱ テンプレートをプリコンパイルヘッダにしたのが悪いのかな ・・
日記はMeadowにでm(ry
>>300 ヘッダのインクルード順序を変えてみれ。
自分は面倒なので#ifとか使ってインクルード順序をすぐに変えられるようにしてる。
例:
#if 0 //ここを1にしたり0にしたりする。
#include <boost/regex.hpp>
#include <algorithm>
#else
#include <algorithm>
#include <boost/regex.hpp>
#endif
Meta-Programming 専用のスレってない?
あったけど、ここに統合。
305 :
デフォルトの名無しさん:05/02/11 13:36:27
テンプレートを使ったクラスでundefined referenceがでます。
ソースは次のようなものです。プリプロセッサは省略してあります。
//temptest.h
template<class T> class temptest{
public:
temptest();
};
//temptest.cpp
template<class T> temptest<T>::temptest(){}
//main.cpp
int main(){
temptest<int> t;
return 0;
}
gccでは "undefined reference to `temptest<int>::temptest(void)"
VisualC++6では "public: __thiscall temptest<int>::temptest<int>(void)は未解決です"
というエラーです。
ちなみに定義をインラインにしたらうまくできました。
どなたか解決方法を教えてください。
>>305 templateの定義はヘッダに書かないとダメ、ということになってます。
そんな決まりがあったんですか。
でもSTLのインクルードファイルを見たところ宣言だけのようですが、
STLは特別なんでしょうか。
STLもヘッダの下のほうに書いてあるんじゃねーの
STLも例外ではないよ
クラステンプレートに実体がなくてもその後ろにクラスメンバのテンプレートの実体が定義されてるはず
stlportだとcppをヘッダからincludeしてたとおもう
ヘッダからcppをインクルード・・・萌えるな。
>>307 temptest.cpp コンパイル時には class T が何だか解らないので
コンストラクタは生成されない
↓
main.cpp コンパイル時には temptest<int> のコンストラクタが
どこかにあるものとしてコンパイル
↓
リンクしてみたら、どこにもいない
明示的にインスタンス化するよろし。
//temptest.cpp
template class temptest<int>;
exportキーワードをまともに実装した処理系はComeau C++だけでしょ。
もう諦めてexportを標準から外した方が良いんじゃないかとさえ思ったり.
現状,exportによる利得というのがほとんど無いみたいですし.
つーか既に実装しなくていいよもう、ってことになったんじゃなかったか?
>315
ソースきぼんぬ.
export周りは泣きそうなほどグダグダみたいですし,さもありなんですけど.
それがC++クオリティ
>>316 D&E日本語版読んでみ。
exportは未だに実装してないといけない規格になっている。
exportって何?
るby
shared_ptrとかintrusive_ptrのリファレンスカウント操作って
引数で値渡しすると呼び出しのたびに操作しますよね。
最適化によるコード削減を阻害しないでしょうか?
特にテンプレートを展開したもののコードがどうなるかが気になります。
>>321 適材適所で。
それからテンプレートの勉強もね。
>>322 要するにオーバーヘッドはかかるというお答えという理解でよろしい?
intrusive_ptrの参照を渡せばいいんですけど、ポインタの置き換えに使うつもり
でいるといまひとつ面倒というか泥くさいというか。
あと、これらのコンテナをfor_eachなどで処理するときのbind(+lambda)で、
_1 と書くだけじゃdeductionしてくれず、bind(&HogePtr::get, _1)
のようにしないといけないのが面倒で、
これを何とか自動でやってくれるようにする方法はありませんか。
HogePtrという派生クラスを作ってポインタから暗黙的にキャストさせると
一番簡単にコンパイラを黙らせられるんですが、今度はコンテナを処理するときに
毎回HogePtrを作って比較するというコードを出してくるようになるので、
なるべく派生はさせずに済ませたい。
参照カウンタによるオーバーヘッドが許せないのなら、
shared_ptr系は精神衛生上使わないほうがいいと思う。
>>323 恐ろしいことだが君のようなハッカーには
それらはもうレガシーだ。boostなのにね。
sandboxにModern C++ Designのを移植した
policy_ptrというのがあるので見るべき
これはなかなか強烈だよ
328 :
デフォルトの名無しさん:05/02/18 12:12:10
>>326 ポリシーベースの派、前に検討して却下してshared_ptr達が採用されたのに
なんで今更?
>328
その議論読んでみたいんですがどこにありますか?
policy_ptrは「shared_ptrは重い」といった主張を持つユーザに対する
選択肢の一つとして提供されるのだと思いますよ.
そもそもpolicy_ptrはshared_ptrなどの既存のスマートポインタに取って代わるものではなく,
むしろそれらと相補関係にあって共存するべきものですし.
なのでshared_ptrを"legacy"と表現するのは恐らく適切ではないです.
ここら辺のもう少し詳しい議論は以下のスレッドや
policy_ptrのドキュメントのFAQあたりが参考になると思います.
http://thread.gmane.org/gmane.comp.lib.boost.devel/116983
似たような*_ptrばっか増やして、
馬鹿じゃないの?
ふざけてるの?
>>330 C++ ってそういうもんだよ。人によって用途も違えば、実行環境のリッチさも
天と地ほど違うので。
新規にクラスを作るならば、COM のように侵入型の参照ポインタにして、
intrusive_ptr で管理するとか
STLかboostあたりに、ある条件を満たすものをoutput_iteratorにコピー
するような関数はないでしょうか?
boost::mplにcopy_ifというそれらしい名前のがあるんですが、
使い方がさっぱりわからない……
なぜか std に copy_if ないんだよね・・・
boost::filter_iterator と std::copy でなんとか汁
std::remove_copy_if(first, last, std::not1(pred));
ごめん。
std::remove_copy_if(first, last, out, std::not1(pred);
だ。
今回は元のコンテナを変更したくないのでremove_copy_ifは使えなさそうです。
結局自分で書きました。
自分でforループを書くと頭悪くなったように感じるので、
これくらいstdに入れておいてほしいものです……。
template <class InputIterator, class UnaryFunction, class OutputIterator>
void copy_if(InputIterator begin, InputIterator end,
OutputIterator result,
UnaryFunction pred) {
for ( ; begin != end; ++begin)
if (pred(*begin)) {
*result = *begin;
++result;
}
}
g++のヘッダを見るとconcept checkとやらを入れたほうがいいらしいのですが、
何を使えばいいのかよくわからんです。boostに道具があるんでしょうか。
remove_copy_ifも説明がよくわからんのですよね。
削除するのに大きさが変わらないってどういうこと?
>>338 remove_copy_ifは入力シーケンスを変更しないよ。
>>339 おお、本当だ。コードを見るとほぼそっくりではないですか。
今までremove_copy_ifは元のを破壊的に変更しつつ、削除したものを
コピーするのだと思っておりました。
名前がミスリーディングだと思うのです……。
>>340 忘れてました。というか気にしてなかったのですが、返すべきですね。
struct NURUPO
{
template<typename T> operator T*() { return 0; }
};
int ILoveNurupo()
{
NURUPO mynurupo;
return (int)mynurupo[0];
}
vc7.1とgcc3.3にガッ
なんか違わないか?
テンプレートの特殊化ってどこに書きますか?
以下のように特殊化する型の定義と一緒に書くと、
* primary.h
#include <iostream>
template <class T>
inline void foo(const T&) { std::cout << "primary\n"; }
---
* specialized.h
#include "primary.h"
struct bar {};
template <>
inline void foo(const bar&) { std::cout << "specialized\n"; }
---
* troublesome.h
struct bar;
bar& get_bar();
* troublesome.cpp
#include "specialized.h"
bar& get_bar() { static bar b; return b; }
void trouble1()
{
foo(get_bar()); // #1
}
---
* main.cpp
#include "primary.h"
#include "specialized.h" // #2
#include "troublesome.h"
int main()
{
foo(get_bar());
return 0;
}
---
#1 と #2 をコメントアウトしたりしなかったりで実行結果が変化します。
具体的には #1 と #2 の両方をコメントアウトした場合 primary が出力されます。
かといって、極端な話 STL のヘッダファイルに書き足すわけにもいけませんし・・・。
template<class T> class A
{
public:
void hoge() { }
void foo() { }
// 他にいろいろなメンバがある
};
というクラステンプレートがあって、プログラム中でA<T>::hogeだけどこからも使われなかったとき
A<T>::hogeのコードは生成されるのでしょうか?
>>348 されない。だから定義しなくても大丈夫。
一応標準としてはAの暗黙のインスタンス化ではhogeはインスタンス化されません.(14.7.1/1)
ちなみにAの明示的インスタンス化の際にはhogeのインスタンス化が伴います.(14.7.2/7)
>350は狼少年
>>348 Modarn C++ Designの1.8に、生成されないことを前提にした技法があったな確か。
シンタックス・チェックだけは、実装によっては行われるんだったっけか。
Modern ね
スマソ
AdobeのASLもここでいいんかな?
使われているプログラミング技法を語るならここかな
あるいはBoostスレか
以下のコードで complex を set に入れようとしたところ、
「stl_function.h:197: error: no match for 'operator<' in '__x < __y'」
とか言われてしまうのですが (g++ 3.3.3)、原因が分かりません。
何がおかしいのでしょうか。
#include <complex>
#include <set>
using namespace std;
bool operator<(const complex<int> &a, const complex<int> &b)
{
return real(a) < real(b) || (real(a) == real(b) && imag(a) < imag(b));
}
int main()
{
set<complex<int> > s;
s.insert(complex<int>(1, 2));
return 0;
}
>>359 <set>の中からそのoperator<()が見えていない。しかしoperator<()を
#includeよりも前に持ってくると今度はcomplexが定義されていない。
しかしstd名前空間内部のものを先行宣言することは許されていない。
自分で関数オブジェクトを定義するしかない。
namespace std {
bool operator<(const complex<int> &a, const complex<int> &b)
{
return real(a) < real(b) || (real(a) == real(b) && imag(a) < imag(b));
}
}
で通ったけど、これってやっていいことだっけ……?
>>360 > <set>の中からそのoperator<()が見えていない。
これは関係ない。どうせグローバルのoperator<は使われない。
>>361 結論:ダメ
宣言や定義をstd名前空間に加えてはならない。今回の場合、struct
std::less<>の特殊化も考えられるが、後述の規定によりuser-definedな名前で
特殊化しない限りundefined behaviorとなる。
17.4.3.1 Reserved names -1
It is undefined for a C++ program to add declarations or definitions
to namespace std or namespaces within namespace std unless otherwise
specified. A program may add template specializations for any standard
library template to namespace std. Such a specialization (complete or partial)
of a standard library template results in undefined behavior unless
the declaration depends on a user-defined name of external linkage
and unless unless the specialization meets the standard library requirements
for the original template.
>>362 #include <set>
using namespace std;
struct hoge{int x;};
bool operator<(const hoge& a, const hoge& b){return a.x < b.x;}
int main(){
set<hoge> s;
s.insert(hoge());
return 0;
}
これ通らない?
>364
それはhogeとoperator<が同じ名前空間(グローバル)で定義されているので通りますよ.
std::complexを引数とする呼び出しからoperator<が見えるためには
operator<がstd名前空間で定義されていないといけないです.
でもそのような定義をstd名前空間に追加することは許されないので(>363),
自分で関数オブジェクトを書いて(>360)それをsetのテンプレート引数に与えるしかないです.
で、結局こう、と。
#include <complex>
#include <set>
using namespace std;
template <typename T>
struct complex_less: binary_function<complex<T>, complex<T>, bool> {
bool operator() (const complex<T>& a, const complex<T>& b) {
return real(a) < real(b) || (real(a) == real(b) && imag(a) < imag(b));
}
};
int main () {
set< complex<int>, complex_less<int> > s;
s.insert(complex<int>(1, 2));
return 0;
}
>>360-366 皆さんありがとうございます。よく分かりました。
ちゃんと勉強しないとダメだなぁ〜 orz
string とか pair が std 名前空間に operator < を定義しているから
ADL のせいで operator < を std 名前空間の外に探しに行かないという認識であってますか?
↑俺には断言できん
↓あってるのか?
あってる。
>>368 あってるぞ。
よし、俺ツーポイントゲット。
その為に less がテンプレート引数になってるんではないのか。
…と、こないだ初めて map で less を使った俺が言いました。
練習で push_back_if なるものを書いてみたのですが
駄目だしお願いします。
template <typename IIte, typename Container, typename Pred>
void push_back_if(IIte b, IIte e, Container &c, const Pred p)
{
for(;b!=e;b++)
{
if(p(*b)) c.push_back(*b);
}
}
insert_if とか copy_if ってないんですか?
あったら便利だと思うのですが・・・。
copy_ifはある。あとはback_inserterを組み合わせて使えばよし。
> copy_ifはある。
ウソだった。標準ではない。すまん。
>>373 残念ながらcopy_ifは標準にはない。どっかに作っておいたら?
//copy_if
template <typename InputIterator,
typename OutputIterator,
typename Predicate>
inline
OutputIterator
copy_if(InputIterator begin,
InputIterator end,
OutputIterator destBegin,
Predicate p)
{
while (begin != end)
{
if (p(*begin)) *destBegin = *begin;
++destBegin;
++begin;
}
return destBegin;
}
>>373 > for(;b!=e;b++)
++bにしたほうがいい。
>377
また荒れるようなことを
いやいや荒れるまでもなく当たり前の事ですよ
荒れてもいいから理由を教えろ
>>381 後置インクリメントだと、一時オブジェクトが必要になるから。
POD型の場合でもレジスタを余計に必要としたりね。
#それが理由で後置インクリメントを持たないクラスも作ることも多いし。
C++より++C
> POD型の場合でもレジスタを余計に必要としたりね。
は?
385 :
デフォルトの名無しさん:05/03/13 03:26:57
今 typeof が使えるコンパイラって g++, icc の他にどんなのがある?
typeofなんてぶっちゃけ template つかってないと殆ど使わんだろうしここでいいよね。
RTTIとテンプレートはあまり関係ないだろうと思いつつ、
ほとんどのメジャーなコンパイラは扱えますよ。
typeidじゃないよ。
メジャーじゃないコンパイラは"ほとんど"に含まれない言葉のトリック
そういうもんだいではない
#define FOR_EACH(RANGE, ITERATOR) \\
for(boost::range_iterator::< typeof(RANGE) >::type ITERATOR \\
= boost::begin(RANGE); \\
ITERATOR != boost::end(RANGE); \\
++ITERATOR)
int a[3] = {1, 2, 3};
FOR_EACH(a, it){
cout << *it << endl;
}
struct plus
{
template<class LHS, class RHS>
typeof(l + r) operator()(LHS const &lhs, RHS const &rhs) const{
return lhs + rhs;
}
private:
LHS l;
RHS r;
};
391間違えました.スレ汚してすいません
template<LHS, RHS>
struct plus_result{
typedef typeof(l + r) type;
private:
LHS l;
RHS r;
};
struct plus
{
template<class LHS, class RHS>
typename plus_result<LHS, RHS>::type operator()(
LHS const &lhs, RHS const &rhs) const
{ return lhs + rhs; }
};
typeof って何で標準に入る予定ないの?
最初からplus_resultのとこにtypeofを書けばいいような?
条件Aに適合する場合にBを適用するという意味で
apply_if を書いてみたのですが、駄目だしをお願いします。
template <typename IIte, typename CheckPred, typename ApplyPred>
void apply_if(IIte begin, IIte end, CheckPred check, ApplyPred apply)
{
for(;begin!=end;++begin)
{
if(check(*begin)) apply(*begin);
}
}
>>396 じゃ遠慮なく。
・名前の省略するな。(×IIte → ○InputIterator)
・Pred は predicate(述語) の略なので、 bool を返す関数以外には使うな。(×ApplyPred → ○UnaryFunction)
・*begin が繰り返されているのは良くない。
・std::for_each() に倣って UnaryFunction を戻り値としたほうがいいかもしれない。
>>397 細かいことを言えば、
InputIterator に apply はまずい。
InputOutputIterator じゃ長いけど。
とりあえず試しに Visual C++ Toolkit 2003 を使ってみたけど、
typeof() は使えない模様。__typeof とかなんかあったりするのかな?
>>398 イテレータのコンセプトを表すという意味で InputOutputIterator はありえない。
出力も兼ねると言うことなら、現行の規格では ForwardIterator が候補になるだろう。
しかしここも std::for_each() に倣って InputIterator とするのが正解だろう。
なんなんだよ、typeof()って?
初めて聞いたぞ。
type_infoクラスとtypeid演算子ならC++にあるけど、
typeof()は何をするためのもの?
>>401 まず最初に言っておくと、typeofは今のところまだ標準には無い。
で、まぁ名前の如く変数の型を得る演算子(?)の事。
Type a;
typeof(a) b = a;
みたいに使える。
この例では a の型が分かってるけど、Expression Template なんかの場合はどえらい事になっちゃうっしょ。
って分かりにくいかなぁ。誰か分かりやすい例キボンヌ。
その程度だとtypeid, type_infoとどう使い方が違うのか見えんな。
テンプレート宣言の
template<typename HOGE>
を適宜、
template<typename HOGE, typename PLUS_TYPE>
にすれば回避できるんじゃないの?
曖昧さの解決にもなるし。
というか、C++とtypeof()は相性が最悪な気がする。
多重継承さえ嫌がる人が多いというのに、
typeof()は、無駄にデバッグ作業を増やさせるだけではないか?
>>400 ForwardIteratorが正しいね。
しかし、InputIterator で要素の変更を行うのは論外では?
for_each()は変更を伴わない関数。
本質的に違う関数に倣うという理由付けも理解に苦しむ。
>>403 うーん、例が悪いでしょうかねぇ。ただ、typeidと決定的に違うのが、
「コンパイルタイムに決まる」、という事。
んだから、「謎の型を宣言、定義可能」って事なんですけどね。
明日から海外飛ぶんで誰かフォローよろ。
俺も来週から地方飛ばされるんで
誰か助けてくれ
俺はneetなんである意味助けてくれ
>>408,409
そのままキャッチされない例外に飛ばされて人生の強制終了。
C++よりMLの方がいいよ。
メーリングリスト
>>397,398,400,401,405,406
参考にしたいと思います。ありがとうございます。
C++よりMLの方がいいよ。
このスレが不要になるぐらい明快
そうか、typeofはgccとintel以外じゃ使えないのか。
クラス階層のメンバを辿るときとか便利なんだよな。
node->get_parent()->get_view() とかで参照をとるとき、一回だけだと
その場に書くけど長いと面倒なので何か別名を割り当てるためだけに
ローカル変数に代入するわけだ。
そういうとき、
#define LET(var,exp) typeof(exp) var = (exp)
とかすると
VeryVeryLongClassName parent_view = node->get_parent()->get_view();
のかわりに
LET(panent_view, node->get_parent()->get_view());
と書ける。非常にラクチン。
boostのlambdaみたいにすればtypeofなしでも同じようなことができるかも。
>>418 boost spirit typeof
>>420 Metrowerks CodeWarriorでの話。
__typeof__()演算子があって、これは常に使える。typeof()演算子を使うには
#pragma gcc_extensions onとする必要がある。こうすると、以下のGNU Cの言語
拡張機能を利用します。
・auto変数の構造体、または配列を、定数以外の値で初期化することを許可します。
・sizeof( void ) == 1
・sizeof( function-type ) == 1
・評価式の内部のGCCステートメントと宣言を、制限付きでサポートします。
・#undefがその前にないマクロの再定義。
・GCCのtypeofキーワード。
>418
>boostのlambdaみたいにすればtypeofなしでも同じようなことができるかも。
逆だと思いますよ.lambdaも状況は似たようなもので
むしろlambdaもtypeofがあればいろいろうれしいです.
でもboostのtypeofの実装はさすがにやりすぎな気が・・・
そもそもtypeofの機能をライブラリで提供する/できるというのが異常というか
gcc 3.4のバグだろうか。
テンプレート関数の中で
boost::mpl::identity<typeof(foo->get_bar())>::type bar;
と変数を定義しようとすると何故か
expected `;' before "bar"
というエラーになる。
普通の関数の中なら問題なく通るのだけど。
>>426 サンクス。
typenameは試したはずなんだけど……と思いつつやってみると
コンパイル通りました。吊ってきます。
Boost.Serialization の
#include <boost/serialization/shared_ptr.hpp>
にある
#define private public
#include <boost/shared_ptr.hpp>
#undef private
って、shared_ptr の方を変更してもらえないんですかね?
別のスレッドで Boost.Serialization を教えてもらったんですけど、
これが、ちょっと気になります……。
変更して貰えるわけないだろ、氏ね(ここまで一筆書き)
430 :
428:2005/03/30(水) 02:21:20
>>429 Boost 同士ということで friend にしてもらうくらいなら、
と思ったんですが、直接には関係しない物のために変更するのは、
やっぱり無理ですよね。
そういうのはここで訊くよりboostのメーリングリストを検索した方がいいのでは。
432 :
428:2005/03/30(水) 05:05:42
>>431 読んでも分からなさそうと言う事で避けてました。すみません。
で、検索してみたら、そのままの議論がありました。
が、やっぱり分かりませんでした。orz
ただ使うだけにします。ありがとうございました。
そういう場合はスレッドのURLとか貼っておくといいかもね。
Serializetionがオブジェクトを覗き見しなきゃいけないことを
>>428は理解してないのか?
shared_ptrの方で変えたら、通常利用で保護出来ないじゃないか。
437 :
428:2005/03/31(木) 11:07:00
>>436 それです。
shared_ptr の人も交えて、実装に立ち入った問題点などが議論されていて、
日頃使っているだけの私では、良く分かりませんでした。
>>437 つか、Thread Index で変なとこに飛ばされて、
議論が追っかけずらいんだよね(´・ω・`)
440 :
デフォルトの名無しさん:2005/04/10(日) 19:16:42
Spiritのアクションってなんで2引数必要なの?
値を代入したい時は冗長になるぅ...
expr = (str_p(L"1"))[boost::lambda::_1,boost::lambda::_2,data=1];
template<class T> class A
{
public:
A(const A&); // 引数
A func() // 返り値
{
A a; // 自動変数
return a;
}
};
クラステンプレートで上記のコメントのところのように
Aとだけ書いた場合A<T>と同じ意味になる、という解釈は正しいですか?
443 :
441:2005/04/12(火) 11:09:04
鬼車みたいに
マルチバイトで正規表現使えると速度面では有利なのかな?
ワイド文字で
System.Text.RegularExpressions(C#)
boost::wregex
boost::expressive
boost::spirit
試してみたけど敵わなかった...
鬼車>>C#>=boost::wregex>>expressive>>>>>>spirit
445 :
444:2005/04/22(金) 04:52:13
>>444 spiritのパーサの型がわからんかったんで
毎回生成してたは...道理で遅いはずや...
typeid(parser).name()で出力された型にparser保存してループ回したら
鬼車=spiritになったわ...
逝ってくる...
CommonLispの正規表現が最速
>>445 当たり前だ。C++が遅かったら、コンパイラ言語を使って正規表現を扱う意味が
ないやんけ。
コンパイラ言語?
式テンプレートを使ったメタプログラミングのこと?
インタプリタ言語と比較してるだけっしょ
またなんかミクロな揚げ足取りしてるんだろうね、きっとw
言い負けるのが余程悔しいんだろうな。
リアルな世界では気の強さが災いして、友達どころか彼女もいないと思われる。
家族にも総スカン。
>>453 どうしてそういう返事をつけるのかな?
普段よっぽど抑圧されてるのか? もっと自分を愛そうね。
スレタイ嫁
>>447は、C++のコードをコンパイルして実行から速いと言っているのか、
汎用のDFSマシンじゃなくて、式テンプレートを使ったメタプログラミングで、
専用レクサーを生成して実行しているから速いと言っているのか、
どっちなんだ? 両方か?
GCC 4.0.0 に TR1 が来ましたね。うれしい。
ソースは boost のごちゃごちゃしたコンパイラ分岐が無くなった分、
だいぶすっきりした印象
459 :
445:2005/04/24(日) 10:46:47
spiritの型導出のためにファイル登録型のtypeof作ってみた。
#pragma once
#include<fstream>
#include<string>
#include<typeinfo>
template <typename T> struct id_of{enum {val=1};};
template <int N> struct id_to_type{};
template <> struct id_to_type<1>{};
#include"type_id_dynamic_impl.h"//(初回は空ファイルを用意)
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)
#define typeof(x) id_to_type<obj_class_id(x)>::type
460 :
445:2005/04/24(日) 10:47:24
template<typename T> static void make_typeof(const T&,int ID)
{
std::string class_name = (std::string)(typeid(T).name());
for(int i=0;i<class_name.length();i++){
if(class_name[i]==':')class_name[i]=';';
else if(class_name[i]=='<')class_name[i]='(';
else if(class_name[i]=='>')class_name[i]=')';
}
std::string include_filename = "type_id_dynamic_impl_"+class_name+".h";
std::string include_file = "#include\""+include_filename+"\"";
std::fstream fo_d( "type_id_dynamic_impl.h" );
std::string buf;bool check=false;std::istream si(fo_d.rdbuf());
while(std::getline(si,buf))
if( buf==include_file )
check = true;
if(!check)
fo_d << include_file << std::endl;
fo_d.close();
std::ofstream fo( include_filename.c_str() );
fo <<"#pragma once" << std::endl;
fo << "template <> struct id_of< " << typeid(T).name() << " > { enum{ val = " << ID << " }; };" << std::endl;
fo << "template <> struct id_to_type< " << ID << " >{ typedef " << typeid(T).name() << " type; };" << std::endl;
fo.close();
}
461 :
445:2005/04/24(日) 10:49:54
int main()
{
int a=100;
make_typeof(a,1212);//初回に必要
typeof(a) aa=100;//make_typeof実行後に有効
}
これってtypeofを使う前にmake_typeofを書いた実行ファイルを走らせないといけないですよね?
実用上かなり使いにくくないですか?
463 :
445:2005/04/26(火) 00:50:17
>>462 それは承知の上、自動で登録できる代償だと思ってる。
でも、type_id_dynamic_impl.hを書き換えるだけにすべきだろうな...
(ファイル大量発生とMAX_PATH超えちゃう問題あるだろうし)
登録してない場合はこんな感じでコード切り替えりゃ済む問題だし、
常用できないという点には同意。
#if if_exist_typeof(a)
typeof(a) aa=100;
#else
make_typeof(a,1212);
#endif
BOOST_TYPEOF_REGISTER_TEMPLATEは飾りなんです
偉い人にはそれがわからんのです
俺の話を聴け〜♪
五分だけでいい〜♪
俺しかいない羊羹マン
ノシ
質問です。
以下の要件を満たす型に対するtemplate class の
特別バージョンを作ろうと考えています。
・任意のContainer
・Container::value_typeがstd::pair
・Container::value_type::first_typeがint
・Container::value_type::second_typeは任意
例えば以下のようなものです。
std::vector<std::pair<int, int> >
std::deque<std::pair<int, char*> >
std::map<int, std::string>
これを実現するのに、どういった記述を行えばよいのでしょうか?
template<typename T> // これが一般の型を対象としたtemplate class である場合
class A {
//...
};
template<typename T, typename U> // ここらの書式は?
class A { // ここは?
// ?????....
};
よろしくお願いします。
>>468 ↓で map_with_string 以外は成功するみたい。(@ g++ 3.4.1)
そう簡単じゃないな。
#include <utility>
template< typename T >
struct A
{ static bool const is_specialized = false; };
template< template< typename > class ContainerTemplate , typename PairSecond >
struct A< ContainerTemplate< std::pair< int , PairSecond > > >
{ static bool const is_specialized = true; };
#include <vector>
#include <deque>
#include <map>
#include <string>
#include "boost/static_assert.hpp"
typedef std::vector<std::pair<int, int> > vector_with_int;
typedef std::deque<std::pair<int, char*> > deque_with_pchar;
typedef std::map<int, std::string> map_with_string;
BOOST_STATIC_ASSERT( A< vector_with_int >::is_specialized );
BOOST_STATIC_ASSERT( A< deque_with_pchar >::is_specialized );
BOOST_STATIC_ASSERT( A< map_with_string >::is_specialized );
470 :
468:2005/05/08(日) 14:04:40
ありがとうございます。なんか凄い構文ですね…
vector,dequeとmapの特別バージョンを一緒に出来ない件に関しては、
以下のような感じでごまかすことにします。
template <typename T>
struct Base {
// implementation
static bool const is_specialized = true;
};
template < template <typename> class ContainerTemplate,
typename PairSecond>
struct A<ContainerTemplate<std::pair<int, PairSecond> > >
: public Base<A<ContainerTemplate<std::pair<int, PairSecond> > > > {
};
template < template <typename, typename> class ContainerTemplate,
typename PairSecond>
struct A<ContainerTemplate<int, PairSecond> >
: public Base <A<ContainerTemplate<int, PairSecond> > > {
};
471 :
468:2005/05/08(日) 14:56:37
すみません、訂正です。
: public Base<ContainerTemplate<std::pair<int, PairSecond> > >
: public Base<ContainerTemplate<int, PairSecond> >
でした。
std::vector<int, MyAlloc>なんかが、特殊化される悪寒w
std名前空間のものを
std名前空間のもので特殊化ないし部分特殊化するのは
可能だがやっちゃダメ
>>472 MyAlloc どころか普通の std::vector<int> も特殊化される罠
>>473 この場合、特殊化してるのは vector/deque/map じゃなくて
A のほうだから問題ないんじゃないかと思うんだが
475 :
468:2005/05/09(月) 13:06:57
Baseで typedef typename T::value_type::first_type first_type
とか、諸々のstatic_assert置いておけばなんとかなると踏んでたんですが、
やっぱ変でしたかねぇ。
476 :
468:2005/05/09(月) 13:22:32
たびたびすみません、これだとA<std::vector<int> >が作れないや。
勉強して出直します。
477 :
473:2005/05/09(月) 16:30:48
478 :
468:2005/05/09(月) 17:44:25
>>473 468では、Aに渡す型の例としてvector,dequeをあげたのであって、
vector,dequeの特別バージョンを作ることを意図したわけではないのです。
>468
ユーザ定義型が絡む場合ならば,std::vector等のstd名前空間内のテンプレートを
特殊化することは許されているんですけれどね.
そもそも468は恐らくソート済みシーケンスとstd::mapを汎用に扱おうとする意図だと
思いますけれど,これらは各種メンバ関数の宣言その他もろもろからして違うので
汎用に扱おうとするのはかなり無理がないですか?
480 :
468:2005/05/09(月) 18:44:11
何度もすみません。
>そもそも468は恐らくソート済みシーケンスとstd::mapを汎用に扱おうとする意図だと
>思いますけれど,
その通りです。
>これらは各種メンバ関数の宣言その他もろもろからして違うので
>汎用に扱おうとするのはかなり無理がないですか?
無理がありました(汗 いろんなことが出来ませんでした。
とりあえず設計が悪かったということみたいです。
>480
それがやりたいならstd::vectorやstd::dequeをラップして
std::mapの要求に合うようにするアダプタ作るのが恐らく最良じゃないかと思います.
それを状況に応じてstd::mapととっかえひっかえする感じで.
boostにそんな感じのクラスなかったっけ?
似たようなニーズがあってboostを眺めたらあったので後で余裕があったら使おうと
思いつつ、遅いけどその場はstd::listで済ませたという覚えがある。
そういやその後試してなくてそのままになってるな。
multi_index_container
>>482 キーと値のアクセスの汎用化、ということなら property_map なんかもそうかな。
あとは boost-sandbox に associative_vector,vector_set なんてのもあるみたいだね。
>>480 まあ実用性のことは置いておいて、メタプログラミングのいい勉強になるかな、
と思ってちょっと書いてみた。
ここは BOOST スレじゃないので、敢えて boost::mpl とかは使わず。
template <class T0, class T1>
struct is_same_type {
static const bool value = false;
};
template <class T>
struct is_same_type<T, T> {
static const bool value = true;
};
struct sfinae_type {
typedef char one;
typedef struct { char arr[2]; } two;
};
template <class T>
struct has_key_type : sfinae_type {
template <class U> static one test(typename U::key_type*);
template <class U> static two test(...);
static const bool value = (sizeof(test<T>(0)) == 1);
};
template <class T>
struct has_value_first_type : sfinae_type {
template <class U> static one test(typename U::value_type::first_type*);
template <class U> static two test(...);
static const bool value = (sizeof(test<T>(0)) == 1);
};
template <class T, bool HasKeyType, bool HasValueFirstType>
struct A_specialized_impl {
static const bool value = false;
};
template <class T, bool HasValueFirstType>
struct A_specialized_impl<T, true, HasValueFirstType> {
static const bool value =
is_same_type<int, typename T::key_type>::value;
};
template <class T>
struct A_specialized_impl<T, false, true> {
static const bool value =
is_same_type<int, typename T::value_type::first_type>::value;
};
template <class T>
struct A_specialized
: A_specialized_impl<
T,
has_key_type<T>::value,
has_value_first_type<T>::value
> {};
template <class T, bool Specialized = A_specialized<T>::value>
struct A { ... }; // 通常版
template <class T>
struct A<T, true> { ... }; // 特殊化版
>485
細かいことですけどmapのkey_typeってconstですよ.
SFINAEのこういう使い方はあくまで
「必要条件を満たさないものを振り落とす」ってだけなんですよね.
それにできることが基本的な型特性と内部型の存在のテストくらいだし・・・.
せめてメンバ関数の存在をテストできればもう少し面白いと思うんですけれど.
>>487 いや、value_type が pair<const Key, T> なのであって、
key_type は Key のままだよ。
そうでないと一時変数作れないし。
>>487 > せめてメンバ関数の存在をテストできればもう少し面白いと思うんですけれど.
typeof(メンバ関数)で何とかなります。
>488
マジボケしてました・・・.
>489
何とかなります?typeofってそもそも非標準ですし.
>>490 まだ sandbox だけど boost::typeof とか。
boost スレかどっかで見たけど、どこだったか忘れた。
>>491 typeofがあってもメンバがなければ単にコンパイルが失敗するだけじゃないですか?
>>492 汎用プログラミングの文脈だと「〜〜というシグネチャを持ったメンバ関数があるかどうか」というテストより
「〜〜という構文でメンバ関数が呼び出せるかどうか」というテストの方が重要だと思うので,
そこで使われている技法は少なくとも汎用プログラミングでは非常に使いづらいような気がします.
それにその技法,言語規格的に結構スレスレなことやってるので,GCCではうまく通らなかったり
VC7.1でもうまく機能しないケースがあったり・・・.
>>493 > typeofがあってもメンバがなければ単にコンパイルが失敗するだけじゃないですか?
traitsみたいなんじゃ不十分で、条件分岐とかしたいという事?
>>493 失敗するだけだね。boost::mpl::has_xxx とかで何とかできないかとも思ったが、
寝不足なせいか、頭がこんがらがってきた。
>>494 そうです.traitsというよりはintrospectionといったほうが適切ですかね.
traitsはユーザが明示的に特殊化する分,確実ですけれど一方で面倒な側面もあると思うので,
ある程度は要件を自動的にテストしてくれたほうが楽かなという発想です.
>>495 boost::mpl::has_xxxは内部型の存在テストにしか使えないです.
>>496 > そうです.traitsというよりはintrospectionといったほうが適切ですかね.
traitsとも違い、
virtual classをinheritしたり、
interfaceをimplementsするのとは違う用途は、
具体的にどういうものを想定しているんですか?
>>497 >具体的にどういうものを想定しているんですか?
いや,あまりろくなことを考えていないんですが,一応,型がどのコンセプトの
モデルなのかを識別するための手段として使えないか,と想定していました.
型がどのコンセプトのモデルであるかを識別できれば,クラステンプレートの特殊化や
汎用関数のオーバーロード選択をより柔軟にできるんじゃないかという考えです.例えば
template<class Iterator, class T>
void replace(Iterator first, Iterator last, T const &x);
という汎用関数があって,TがIteratorの値型に変換可能な型ならstd::replaceの機能で,
TがIteratorの値型を受ける単項述語ならstd::replace_ifの機能といった具合です.
逆に言うと,STLはこのようなコンセプトに基づいたオーバーロード選択の技術がないので
replaceとreplace_ifとに名前を分けざるを得なかった,とも言えると思います.
で,仮に例えばTのoperator()がIteratorの値型で呼び出せるかどうかを
テストできるような実装技術があれば,traitsの明示的な特殊化に頼ることなく
上記のような高度な振り分けができるんじゃないか,という考えです.
ただ,もちろんメンバ関数の存在テストはコンセプトの必要条件を調べられるだけで,
決してコンセプトのモデルであるための十分条件を調べることにはならないのですが・・・.
上記PDFもそうだけど、D&Eの書き下ろし前文(-1章)を見ても、
コンセプト回りの拡張が c++0x でなされる可能性は高いんじゃないかな。
ただ、Stroustrup としても
テンプレート回りのエラーメッセージの酷さを何とかすることや、
テンプレート宣言と定義の分離問題を何とかするために導入したいような
感じだし、基本的にはコンパイル時検査の強化を目的としたものであって、
オーバーロード選択などに使われるようなものではないと思う。
例えば、関数ポインタのシーケンスがあったとして、
operator== による find なのか、operator() による find_if なのか、
コンセプトだけでは判断できないケースもあるわけで。
>>500 > 使われるようなものではないと思う。
けど,使われるようなものではないものに,使われて驚くのがtemplateだしなあ…
>>500 >テンプレート回りのエラーメッセージの酷さを何とかすることや、
>テンプレート宣言と定義の分離問題を何とかするために導入したいような
これは前々からずっと言ってますからねぇ.近い将来標準に導入されると信じていますけれど.
>例えば、関数ポインタのシーケンスがあったとして、
>operator== による find なのか、operator() による find_if なのか、
>コンセプトだけでは判断できないケースもあるわけで。
う,やはりここ突っ込まれますよね・・・.こういう曖昧なケースではユーザが
明示的に曖昧性を解消するような方向を想定してました.微妙ですけれど.
やはり現在の段階では,コンセプトに基づくオーバーロード選択や
テンプレートの特殊化といった発想は飛躍しすぎている感がありますね.
参照templateのパラメータに制限あるのかな?
グローバル変数しか使えないみたいなんだが...
struct A{};
template <A& a>struct C{};
A a;//OK
int main()
{
A a;//NG
C<a> c;
}
>503
14.3.2 Template non-type arguments
4 [Note: Temporaries, unnamed lvalues, and named lvalues that do not have external linkage
are not acceptable template-arguments when the corresponding template-parameter has reference type.
14.3.2-1 の補足。
テンプレートはコンパイル時に生成されるわけで
mainの方のaは実行してみないとどこに作られるかわからないわけで
そのaをテンプレート引数にstruct Cは生成できないわな。
506 :
デフォルトの名無しさん:2005/05/15(日) 21:00:03
VisualC++7.1なんですが、テンプレートコンストラクタの明示的なインスタンス化をしたいんですが
コンパイルが通りません。なぜでしょうか?
class A
{
public:
template< typename B > A( B b){;}
};
template< > A::A< int >( int b); // error C2143: 構文エラー : ';' が '<' の前にありません。 他
template A::A< int >( int b); // error C2143: 構文エラー : ';' が '<' の前にありません。
>>506>>507 多分これ。
14.5.2.5
[Note: because the explicit template argument list follows the function template name,
and because conversion member function templates and constructor member function templates
are called without using a function name, there is no way to provide an explicit template argument list
for these function templates. ]
コンストラクタは関数名を持たないので、メンバテンプレートにされたコンストラクタおよび
変換メンバ関数テンプレートは明示的に実引数を与えられないって事っすね。
C++の不具合とも言えるので、次期C++規格ではfixして欲しいですな。
509 :
デフォルトの名無しさん:2005/05/15(日) 21:56:00
>>506 理解しました。ありがとうございました。
しかし皆さん凄いですね。
>>506 というわけで
「コンストラクタテンプレートぐらいhppに全部書いちゃえば良いじゃない」
もしくは
「コンストラクタテンプレート内の処理を静的メンバ関数に委譲して
(この部分だけはhppに書く必要アリ)
委譲先の静的メンバ関数を明示的にインスタンス化すれば良いじゃない」
ん?これでできてるっぽいぞ。
template<> A::A( int b);
>>511 あれ?本当だね。という事は、template <>の構文がちゃんとメンバテンプレート
に適用されているみたいだね。俺の勘では、明示的特殊化になってなくて、単なる
オーバーロードのような気もするが・・・・
もう少し規格票をよく読んでみる・・・・・
>>508はそしたら違う事に関してなのかな。
>>511 しかし、そのコードは構文的に正しいとは言えないですよね。
謎だ。
特殊化とインスタンス化とを混同してない?
>508が示したように、コンストラクタテンプレートに対して
テンプレート引数を明示する方法は無い。
しかし、(メンバ)関数テンプレートの特殊化を宣言する再には、
テンプレート引数を明示しなくても、関数引数の型から
テンプレート引数の推測が働く。
>>514 明示的特殊化の構文は
template<> delcaration
だから、>511は構文的に正しいと言える。
構文的には確かに正しいのだけれど、もともとの506の要求は
明示的インスタンス化(≠明示的特殊化)なわけで・・・
勉強になった。
>>517 それがどうした?
明示的インスタンス化の構文は
template declaration
だ。あとは同じ。
>>519 すまんすまん。それでVC++7.1で通ったよ。
コンパイラに「これこれのテンプレートをT型でインスタンス化しますた」
とレポートするスイッチがあればいいのに
実体化の位置を決定するルールは結構複雑だからな。
おまえらの必死さに笑った。
C++の中途半端なtemplate機能でメンテ不能の駄作を量産してる様は、
まるでVBで汎用ライブラリを作る馬鹿とそっくりだな。
C++知らないのに、知ってる振りして
がんばって煽るアンタもそうとう必死だが
むしろC++で駄目なのは
テンプレートじゃなくてコンストラクタ
純粋なOO言語と比べると
C++のOOは不完全
>>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(){;}
};
何がしたいのか理解に苦しむ。C++について理解しているとは思えないコードだ。
>>529 これが出来ないから嫌だなと。
>B(){ int a = 略; A::A(a);}
これはAに突っ込む引数aを
Bのコンストラクタ内で生成したい時。
C++ではAのコンストラクタは、Bの初期化リストにしか
置けないので複雑なロジックは難しい。
>B( int a ) : B(){;}
これは多重定義したコンストラクタから
デフォのコンストラクタを予呼びたい時。
デフォのコンストラクタに生成時にかならず呼ばれる
初期化コードを収める。
これが出来ないと全てのコンストラクタに
同じ初期化コードを書かなければならない。
>>530 最初の:AはBの基底クラス。最初にAが構築されなきゃBが構築できない。
2番目の:B() {Init();} B(int a) {Init();hogehoge(a);}
最初のは
static int hoge() {return 略}
B() : A(hoge()) {}
とかすれば。
>>530 そういうことか。
ではどうしたらいいと思う?
Dは両方いけるんだっけか?
>>531 > Aが構築されなきゃBが構築できない
関係ない。
> Init()
Init() の中に初期化リストが書けない。
>>532 hoge() の値を初期化リストで2度使いたくなったらやっぱり困るな。
「略」が軽くて副作用がなければ、2回呼び出すんだろうけど。
要は設計が悪いんだろ。
まあそうだな。C++の設計の悪さは今更いかんともしがたい部分がある。
>>530 > C++ではAのコンストラクタは、Bの初期化リストにしか
> 置けないので複雑なロジックは難しい。
コンストラクタの途中でexceptionが起きたことを考えると、
>>532のような方法で初期化リストを旨く使う方法に頭を悩ませるのが良い。
>>528のやり方ではコンストラクト失敗時のデストラクトの扱いがかなり難しくなる。
初期化リストで上手くできない場合は、
exception safeの事を考えるとコンストラクタ自体がかなり複雑になってしまう。
定義順じゃなくて、初期化リスト記述順だといいのになあと思ったことはある。
>>539 それだと、コンストラクタごとに初期化順が変わってしまう。
Ex.
class foo {
public:
foo() : a_(), b_() {}
foo(int a) : b_(a), a_(a) {}
...;
};
>>540 539はまさにそれを意図しているのだと思うが、何か不都合があるの?
>>541 初期化リストに載ってないメンバはどうすればいい? by コンパイラ
くるしゅうない。よきにはからえ。
構築した順番の逆順で解体することを保証しなきゃならんので
コンストラクタごとに初期化順が変わったら大変だ。
なるほど。それもそうだ。
つーか藻前らEffectiveC++くらい読んどけよ。
547 :
デフォルトの名無しさん:2005/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 :
デフォルトの名無しさん:2005/05/16(月) 20:53:37
あの〜
templateって実はマクロ?
>>547 関数のデフォルト引数でなんとかしろ。同一のテンプレートパラメータの型を
持つクラスは2回以上は定義できん。
>>549 了解、こういうのも出来るといいですね。
いやだから、ディフォルト引き数で何が不満なんだ?
それぞれ特殊化で可能じゃない?もちろんそうするのが良いか悪いかは別。
553 :
デフォルトの名無しさん:2005/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);
自然な欲求だと思います。
>>553 そういう時のためのstd::vectorではないかと思うのだが・・・・
static const uint initialValues[] = {5, 1, 6, 3, 9,};
std::vector<uint> v5 = std::vector<uint>(initailValues, initialValues + sizeof(initialValues) / sizeof(*initialValues));
その例なら
配列を初期化して、std::vectorにぶち込めばいいじゃん
どうしてもやりたいならBOOST_PPで特殊化
部分特殊化。以降略。なんか馬鹿みてえ。
#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);
}
特殊化はイヤというか面倒くさすぎるから、普通はこんなカンジだろうね
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);
}
やはりコンストラクタのオーバーロードに落ち着くか。
>>
そうするまでもなく
普通に多重定義でいいと思うよ。
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;
}
};
ちなみに、 sizeof(char[Dim == 1]) ってのは、
Dim == 1 のときは、1 で、そうでなければ、コンパイルエラーね
どうも読みにくいので、直した
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);
}
おまえらの必死さに笑った。
C++の中途半端なtemplate機能でメンテ不能の駄作を量産してる様は、
まるでVBで汎用ライブラリを作る馬鹿とそっくりだな。
×メンテ不能
○俺に理解不能
565 :
デフォルトの名無しさん:2005/05/17(火) 07:37:28
あーあ、4,5,6って別々にするわけ?テンプレの意味ねー
566 :
デフォルトの名無しさん:2005/05/17(火) 07:41:46
テンプレートはマクロ
www.iba.k.u-tokyo.ac.jp/〜yanai/template_tips.html
>>563 まあ同意。boostとか見てても思うが、言語使用の範囲内でどうにかしようとするから無理が出てくる。
パズルとしては興味深いが、無理やりやってるからどうしてもキモくなる。
新しいプリプロセッサ作ったほうがマシな気がする。
>>566 典型的なアホっぽいが。
exportはComeauでサポートされていることすら知らんようだし。
>>566 > まず最も重要な事実は、templateはマクロであるということである。
そもそも、始めの仮定についてキチンと論証してない時点でアウトだな。
templateはマクロだよ。
マクロと聞いてCやC++のプリプロセッサ(やVBAなどアプリケーション内のスクリ
プティング言語)しか思いつかない人に向けた文章ではなかろ。
>ここではオブジェクト指向に則ったよいtemplateの使い方を模索する。
この時点で道を誤っている気が。
templateの明示的インスタンス化なんて、少し考えれば
使い道などろくに無い機能だとわかるだろうに
しかも使う必要も無い機能だし
それにこだわってる時点で、ダメだなそのページ
ネタをまじめに叩くなよ
574 :
デフォルトの名無しさん:2005/05/17(火) 20:39:55
ねたじゃねーし
templateはコンパイルする前に展開されるからマクロなの
コンパイルする前に展開しちゃったら
タイプセーフは無理じゃないの?
いいよわからん奴は無理に使うな
マクロで使える構文を限定的にして型を認識させたのがテンプレート
みんな好き勝手に「マクロ」の意味を定義して使ってるから、話が噛み合わない
だけでしょ。
おっと、ここで578が正式にマクロの定義とやらを教えてくれるらしいぞ
なにこの意味不明な反応
付き合うだけ無駄でつ
582 :
デフォルトの名無しさん:2005/05/18(水) 07:21:54
普通のマクロでも引数の数を変えられるようなことはできないから
>>553
VC7.1で
std::list<int>使うとポインタの保存のためか
std::vector<int>の3倍近いメモリ使うんだが、
省メモリな実装のlistって無理なのかな?
>>583 SGI STLのstd::slistなら、一方向リストだけど、少しでも少ないかも。
リストすら作りを理解してないのかよ。
std::vectorのresizeコストが気になるようならstd:;dequeとか
つうか双方向リストは最低2つはポインタが必要なんだから当たり前の気がするんだが
588 :
583:2005/05/21(土) 00:47:56
サイズは可変で大きい、挿入削除が定数時間(->list)、省メモリ(->vector)
を同時に満たしたかったので...
とりあえず挿入削除の速いlistを選択したけど、以外とメモリ食うって分かった。
小規模のvectorをlistで繋ぐか584さんのslistつかうのがいい気がしてきた。
双方向リストだとポインタが64bit化したらさらに事態は悪化するのも気になるし...
だから小規模なvectorをつなぐぐらいならdeque使えってばよ
>>587 要素が int で、双方向のポインタがあるわけで
それぞれサイズが同じなら、int の 3倍ですね。
>>585 も指摘してますが、糞当たり前です。
>588
データ構造の勉強からやり直して来い。
s/int の/1要素あたり int の/
>>588 中身の小さいオブジェクトを入れると、相対的にlistはポインタなどの管理部分が
大きく見えてしまうからねえ。
ケースバイケースで使い分けるしかない。
それとstd::slistのiteratorは、forward iteratorなので、bidirectional iteratorのlist
に比べると実行効率の悪いメンバ関数がいくつか存在するから、その点もよく確かめてね。
594 :
583:2005/05/21(土) 01:04:49
dequeだと
中間への挿入、削除した場合に
参照と反復子が死滅。
>>588 テキストエディタみたいに、挿入が同一箇所に連続して発生するようなら
ギャップベクタを検討するといいかも
>>594 それが問題になるなら、もう list しかないんじゃないかなぁ。
「小規模のvectorをlistで繋ぐ」なんてのも、全然ダメだろ。
もはやtemplateの話題じゃなくて、「データ構造とアルゴリズム」の世界だな。
listとかvectorはあるのに、より優れた概念のS式がないのはおかしい
>>598 あなたね(汗
インタプリタじゃないんですから。
>>599 もっと詳しく。
・・・って言っても無駄か。
何もわかってないくせに噛み付いてるの見え見えだもんな。
S式ってツリー構造じゃ無かったっけ?違った?
>>597 STLネタがそっちに向かうのは自然だと思うけど?
> つうか双方向リストは最低2つはポインタが必要なんだから当たり前の気がするんだが
直前の要素のポインタと直後の要素のポインタの排他的論理和演算結果を保持しておけ。
そうしておけばポインタ1つで双方向からリストをたどることができる。
実行時にそれなりのコストはかかるが、、、
>>604 結局サイズは変わらないわけだが。
しかも「ポインタ同士のXOR」?ワケワカラン。
606 :
604:2005/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 というデータ構造。
>>606 代償としてイテレータのサイズが大きくなるから、使い道は微妙だけどな。
>>606 ふーん。
std::list の実装に使われてるのは見たこと無いんだけど、
標準コンテナの実装としては何か問題があるのかな?
と考えたら、イテレータを取得した後に要素の削除・追加をするとマズイような気がした。
>>604 リストを変更しないときのコストはたいしてかからないんじゃないか。
簡単なループの場合、movl (%eax),%eax が xorl (%eax),%eax になるだけだろう。
>>607 イテレータのサイズなんて問題になることがそうそうあるとは思えんが。
前後に追加削除があるとイテレータが無効になってしまうから
std::listとはコンパチにならなくなることの方がまだ問題になりそうだ。
610 :
604:2005/05/21(土) 10:50:55
>>607 イテレータのサイズとリンクリストに保持される各要素のデータサイズを同列で比較するのもどうかと思うが。
イテレータにポインタを2つほど追加したところで、8バイトしかサイズは増えない。
(処理が複雑化する分、イテレータオブジェクトのサイズはもう少し増えると思うが。)
しかし、双方向ポインタにしてしまうと、各要素毎に4バイトの投資が必要となる。
611 :
604:2005/05/21(土) 10:58:43
>>608>>609 確かにイテレータの取得後に前後の要素が追加削除されると痛い。
排他制御の問題を抱え込むから、std::list との互換性は考えない方が吉かと。
>>609 > 簡単なループの場合、movl (%eax),%eax が xorl (%eax),%eax になるだけだろう。
訂正。これ間違い。xor+mov*2(or xchg)になるな。
> サイズは可変で大きい、挿入削除が定数時間(->list)、省メモリ(->vector)
データの格納にset使うのってやっぱダメなのか?
setの中身はconst扱いだけど、外してswapして取り出して消して使ってるけど。
挿入時もヌルデータ入れて跡で要素をswapしてるんで無駄なコピーも出ない用に工夫して、、、
、、、、
vectorはサイズ増えると勝手に自分のコピー作るんで、reserveしなきゃならんので嫌だ。
lispは探索が遅いし。mapはそんなものに使うのもったいないし。
結論 : set使え!
setが泣いてるぞ
listのメモリ効率が気になるような状況でsetなんか使えるかよ
つーか、dequeって要素へのアクセスもそこそこ速くサイズ変更のコストも最小限なのになんで使われんのか。
>>615 dequeって要素へのアクセスもそこそこ速く
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
環境によってはlist並みに遅いわけですが何か?
OSやCPUは敢えて書かないが、STLportとかSTLportとかSTLportとか。
>>606 C++ でポインタにビット毎の論理演算なんて
吉外じみた真似、よく平気で出来ますね。
618 :
604:2005/05/22(日) 08:36:41
>>617 坊やだな、、、
ポインタと言えど所詮はビット列なのだよ。
>>618 reinterpret_castとか使わないといけないんだろ?
環境依存イクナイ(・A ・)!
621 :
604:2005/05/22(日) 08:55:52
>>619 reinterpret_castが即、環境依存につながるとは新鮮な考え方だな。
同じ環境内でキャストして、同じ環境内で元に戻すのであれば、環境依存も何もないだろうに(それを環境依存というのなら、コンパイラが吐くコードはすべて環境依存になるぞ)。
それとも、そういうことすら期待できない処理系が現存するというのか?
(そんなのが出てきた時点で reinterpret_cast は言語仕様から外されるだろうて。)
>>621 愉快な香具師だなお前。
C++の実装と進化の§14.3.3(P420)読んでみろ。
>>622 ○C++の設計と進化
×C++の実装と進化
それから、規格票を優先しろ。
624 :
604:2005/05/22(日) 09:17:26
その本は持ってない。
引用の範囲内だろうから、出典を明記して引用してくれ。
内容を咀嚼して説明してくれてもよいぞ。
625 :
620:2005/05/22(日) 09:35:20
俺の面白いは純粋な意味であって、622と同じ意じゃないですよ
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:2005/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にして何の演算も許さず、元のポインタに戻すことしかできないのであれば、そもそもキャストする意味ないし。 まさかシリアライズするのか?、、、ってそれはあまりにも危険だしな。
>>626 ん?問題ないんじゃない?
同じポインタからは同じ整数になり、
同じ整数からは同じポインタになるっていう射影だよね。
この規格表のいいたいところは要するに、
アドレスが16違っている2つのポインタを、
整数に直した時も16違っているかどうかはわからないよ、
というだけの話じゃん。
629 :
626:2005/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 上に同じです.失礼しました.
magic list はネタとしては面白いが、現実には滅多に使われない
データ構造だな。この手のネタは Hakcer's Delight とか Knuth
センセの本を読むとイロイロ転がってるよ。
あと、現実のプログラミングだと、list に int 一個だけ入れるのも
珍しい気がする。手元のコードをいくつか見直してみたが、わりと
大きめの構造体を繋ぐか、スマートポインタを入れることが多い。
いずれにしてもポインタ二個分のメモリなんて誤差って感じ。
珍しいかどうかは、ともかく
メモリ云々行ってた奴は、たぶん初心者だから
初心者の戯言を、あまり真に受けないほうが
結論はvector使え、でいいのか?
magic list は所詮オナニー
ここはジェネリックプログラミングの話題じゃないのか?
>>635 テンプレートの話題ですよ。尤も、スレタイも読めないなら
このレスも読めない可能性、大。
暇つぶしに作ってた、ヘボコンパイラは出来上がったから
今度は、マジックリストクラステンプレートでも作ってみようかな
作ったらほしい人いる?
学術的な興味なら。
ソースより測定結果をみたい。listやvectorとの比較つきで。
というか作りかけてる・・・
小規模だけど多次元配列のポインタがどうしても必要で、newも使いたくないから
std::vector<std::vector< ...> >
とかで書いてみたんだけど、4次元ぐらいからコンパイル時間が凄くかかる。
ま、コンパイル時に何がおきてるか想像すりゃ当たり前といえば当たり前だし、
コンパイル時だけの問題なので気にしなきゃいいんだけど、
環境になるべく依存しないで(boostとかは使えないし、VC,gcc両方通す必要あり)、
効率の良い方法がありまつかね。std::deque使ってもかわらなさそうだし。
>>643 その「多次元配列」のインターフェースを必要最小限に絞って、
pimpl なり抽象インターフェースなりでコンパイル単位を分ける。
基本だな。
>>644 dクス。
pimplイディオムは詳しくないので、Exceptional C++でも読んでみまつ。
646 :
640:2005/05/25(水) 02:46:33
void reverse() // throw()
{
head_ = decode(sentry_.code, head_);
}
感動してしまった。
649 :
デフォルトの名無しさん:2005/06/06(月) 11:28:39
質問です。
「具現化によって生成された実体」 = 「ユーザー定義ではないスペシャライゼーション」
という理解でいいの?
650 :
デフォルトの名無しさん:2005/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> って何者? 誰か教えてください。
省略されてるだけ。
template <class /*T*/>
class foo;
>>651 サンクスです。とすると何らかの型を受け取るけど、
その型の情報は無視するよ、っていうことなんですね。
これをもとにもう一回読んでみます。
>>650 int f(int i);
int g(int); // これも脳内エラーが出るか?
>>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
のように使うことになりますね。
補足ですが、
使えない == typedefできないということです。
間違ったことは言ってないが、質問の答えとしては完全にズレてるな。
658 :
654:2005/06/08(水) 01:22:29
>>656-657 この場合
>"template テンプレート パラメータ"の意味が理解できないッス。
と書いてあるところから、名前云々は関係ないと思うのですが・・
>>658 会話になってないな。もういいから喋るな。
>>650です。
皆さんありがとうございます。
>>654さんのご意見もとても理解の助けになりました。
typedf templateってどうなったの?
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の一文をテンプレート化できるんだっけ。
>>662 それはだめだろ。
template-templateパラメタのtemplateパラメタ(この場合T)
に言及するのは意味的におかしい。
こうじゃないか?
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;
typedef templateを導入するなら変数templateや名前空間templateも欲しい。
と無責任に言ってみるテスト。
>>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とはどんなもんでしょ?
もしも変数テンプレートがあったとしたらこんな感じ?
template <typename T> const T *NULL = 0;
int *pi = NULL;
char *pc = NULL;
#include <cstdio>
int main() {
std::printf("%p", NULL<void *>);
}
>>667 >int *pi = NULL;
>char *pc = NULL;
これを許すとまた規則が複雑になるな。
class null {
public: template<typename T> operator T*() const { return 0; }
};
const null NULL;
int *ip = NULL;
char *cp = NULL;
printf("%p", (void*)NULL);
でいいような気がす
誰もそんな話ししてないわけだが
>>667 引数とるコンストラクターはどうなるんだ。
typedef template ムチャ欲しいな。
>>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の構文を提案してたはず.
>>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で初期設定しようとし、成功。
が妥当じゃないのか?
>>670 そうでなくて、必要性が全く感じられないと言っている
まともな利用例ぐらい出さないと
>>674 その使い方だと常に明示的にインスタンス化しないといけない
(NULLを利用するたびに型パラメータを与えないといけない)わけですよね?
それは利用範囲が著しく限られませんか?
677 :
667:2005/06/09(木) 15:03:10
ところで俺は変数テンプレートは全く要らないと思うんだけどな。
俺も669と同じようなのを考えたことはあるけど。
>>676 使い道がないのは同意。
ただ、仮に現在のテンプレートの延長で「変数テンプレート」なるものを定義するなら、
>>674で言ったようになるはずだと思った。
>>673のような機能を導入するなら別の名前・構文を考えるべきだと思う。
型推論はされるとして、
NULLみたいに初期化子に使うとちょっと面白そうな…
クラス階層のあるところでPTHREAD_MUTEX_INITIALIZERみたいなやつ。
>>678 確かに「変数テンプレート」という名前は非常にまずいですね.
ただ構文については既存のキーワード使うとするとこれぐらいしかないような気がします.
アドビのオープンソースってど?流行ると思う?
STL、boostを基に、ウィンドウをスクリプトから生成する画期的システム
仮想マシンを実現とか、内容は理解を超えていた (つД`)
いわゆるチョット修正のときに威力を発揮すると思う
SEはどんな些細なこともPGに要望しなけりゃならない
PGは思いつきの修正のために仕事が増えるばかり
だれか人柱になってください、やっぱアドビ待ちなのかな
質問です。
BCC 5.5上のテンプレートのバグはどのようなものが
あるのでしょうか。
・・・特に大きいタイプリストを渡すと、他の特殊化に指定
したクラスが別のクラスに化けるとか、そんなのないですか?
>>683 質問するときはやりたいこと、実際にやったことを書いた方が良い。
>>683 どういうバグかは知らんがboostが満足に使えない。
686 :
683:2005/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とするようにしたら今度は何十の長さでもコンパイルできました。
前者のコンパイルの仕方にバグがあるんでしょうかね・・・
BCCなんか使うなよ
もしかして、クラステンプレートのメンバ仮想関数って勝手に実体化される?
690 :
688:2005/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();
}
こんな感じ。
>>690 それってderived<int>型の変数dを宣言したからderived<int>が実体化されているだけのように見えるが。
692 :
688:2005/06/14(火) 18:28:53
derived<int> が実体化されるのと
derived<int>::foo が実体化されるのは別じゃないですか?
クラステンプレートのメンバって呼ばれるまで実体化されませんよね?
>>688 規格では詳しくは規定されていないっぽい。
実際は
・derived<int>のインスタンスが宣言された
・derived<int>*からbase*の変換が行われた
のいずれかをトリガとして、仮想関数をすべて実体化することになると思う。
694 :
688:2005/06/14(火) 18:40:33
>>693 サンクス。未定義ってことですか。
一応、明示的に実体化しておいたほうがよさそうですね。
>一応、明示的に実体化しておいたほうがよさそうですね。
なんでそうなる?
ついでに、「未定義」と「未規定」は違う。
696 :
688:2005/06/14(火) 18:50:17
ん?
規定はされていなくても、正常に動くことは保証されているってことですか?
697 :
693:2005/06/14(火) 18:57:55
言い方が不正確だったな。
規格には、「メンバ関数は、その定義が必要とされるとき実体化される(意訳)」とある。
で、virtual関数については、いつ「定義が必要とされる」か正確に規定している部分が(俺の見た限りでは)なかった。
従って、virtual関数の正確な実体化のタイミングは規定されていないことになる。
それでも、「必要」になり次第実体化されることは保障される。
698 :
688:2005/06/14(火) 19:22:06
あー、なるほど。
規定されていないのは実体化されるタイミングだということですね。
どうもありがとうございました。
int k = 0;
for (vector< set<int> >::iterator it = v.begin(); it != v.end(); ++it)
it->insert(k++);
を boost::lambda か何かを使って for_each でシンプルに書けませんか?
メンバー関数に bind する仕方がよく分からないんですが・・・
>>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:2005/06/26(日) 19:49:39
メンバ関数に限らず、オーバーロードが絡むと lambda は使いにくいな。
protect要るか?
>>701 C++は名前が重なった場合の簡潔な指名定方法がないしね。
lambdaに限らず面倒。
typeofがBoostに入るそうだから、そのうち頑張って改善されるといいな。
703 :
700:2005/06/27(月) 07:50:29
>>702 こんな感じで変形していったが、途中のやつの
エラーメッセージがひどくて(数100行ぐらい出る)、
何がまずかったのかよくわかってない。
× ((*_1)->*insert)(var(k)++)
× bind(insert, *_1, var(k)++)
○ (protect(bind(insert, _1, var(k)++)))(*_1)
704 :
702:2005/06/27(月) 22:11:02
>>703 その3つの最初から間違ってるよ。
for_eachなんだから_1にはイテレータではなく参照が入る。よって
_1をdereferenceする必要はない。
まあ同じなんだけど、俺ならオーバーロードが絡む場合は
メンバ関数の特定を追い出すかな。
void hoge(vector<set<int> >& v) {
typedef set<int> set_type;
pair<set_type::iterator,bool>(set_type::*insert)(const int&)
= &set_type::insert;
int k = 0;
for_each(v.begin(), v.end(), bind(insert, _1, var(k)++));
}
705 :
700:2005/06/28(火) 00:20:42
>>704 うわ、とんでもない勘違いをしていたよ。
ありがとう。
int array[] = {1, 3, 5};
std::vector<double> v = ...;
int ma = Mean<int *>()(array, array + 3);
double mv = Mean<std::vector<double>::iterator>()(v.begin(), v.end());
こんな感じじゃないか?
for_eachにかけるものではないのね
でも便利そう thx
>>707 のとおりにやってみたけど
コンパイル通らなかったよ
>>706 > 算術平均を求める Mean を書き直すと以下のようになる
> (もちろん Sum も反復子を使うように変更してあることが前提)
ちゃんとSumもコード書いた?
んで、漏れなら、合計値(累積値)を求めるアルゴリズムaccumulateを使い
平均値は:
void f(vector<double>& m) {
double avg = accumulate(m.begin(), m.end(), 0.0) / m.size();
}
のようにして求めるな。分散・標準偏差、RMSあたりも似たような実装ができる。
>>710 わざわざ関数にするのか?
コードの大きさを抑えるのにはいいけど。
>>711 しない。入力が何で出力が何か明確にしたかったので、関数形式で書いただけ。
実際に関数にするなら、template、inline、引数にはconst、戻値の型を明記、あたりが必要です。
蛇足で糞コード晒す。
template <typename T>
struct square : public binary_function<T, T, T> {
T operator()(const T& lhs, const T& rhs) { return lhs + rhs*rhs; };
};
double ms = accumulate(m.begin(), m.end(), 0.0, square<double>()) / m.size();
double rms = sqrt(ms);
double stdev = sqrt(ms - avg*avg);
STLは連続した、同じような事の繰り返し処理には滅法強いな。
>>713 あなたの人生もSTLで簡単になりますよ。
void silly_life(life& your_life)
{
struct
{
static int daily(day& d)
{
d.nebou();
d.nichan();
d.onanu();
d.shigoto();
d.nichan();
d.onanu();
d.neru();
return 0;
}
};
std::for_each(your_life.begin(), your_life.end(), daily);
}
久しぶりにtemplate見たよ。。。C#使いづれ〜。。。orz
それがSTLクオリティ。
語呂悪いな。
速度が重要になるコードを書かなければなのですが、
やはりSTL経由の連続処理は、速度的に不利なんでしょうか?
一応自分なりに、次レスに書いたような実験をしてみたのですが、
プロファイル結果はSTL版hoge()が平均301msに対し、
シンプルなリストhage()の方が平均12msと、圧倒的な差に…。
今更自前リストなんて使うのは、考えただけで頭が痛くて。
なにかテストに落ちがないか、
或いはSTL版速度向上のための抜け道が無いか、教えて頂けないでしょうか。
#include <list>
struct simple_list{
int val;
simple_list* next;
};
template <typename T>
void hoge( T first, T last ){
int sum = 0;
while( first != last ) sum += *(first++);
};
void hage( simple_list* sl_first ){
int sum = 0;
while( sl_first ){ sum += sl_first->val; sl_first = sl_first->next;}
};
int main(){
std::list<int> listInt;
for( unsigned long i=0; i < 100000; ++i ) listInt.push_back(i);
simple_list* sl_first = new simple_list;
simple_list* sl = sl_first;
for( unsigned long c=0; c < 100000; ++c ){
sl->val = c;
sl->next = new simple_list;
sl = sl->next;
}
sl->next = NULL;
hoge( listInt.begin(), listInt.end() );
hage( sl_first );
while( sl_first ){ sl = sl_first->next;delete sl_first; sl_first = sl; }
return 0;
}
>>716 プロファイルでは最適化は有効にしてる?
最適化しないと比較にならないし、最適化すると hoge(), hage() が
sum を返してないので、最適化で処理自体が消えてダメかもしれない。
hoge の sum += *(first++); を { sum += *first; ++first } にすると、少し違うかもしれない。
>>716 最適化した?
うちじゃ
hoge(): 8.46567 ms
hage(): 7.92051 ms
くらいなんだけど
環境はg++ (3.3.5)
720 :
716:2005/07/07(木) 08:08:12
我ながら非道い
sl->next = NULL;を削って
sl->next = new simple_list; を
sl->next = (c != 100000-1) ? new simple_list : NULL; とでも
>>718-719 最適化をすっかり忘れていました。
なぜだかsumを返すようにしてもhogeの方が消えてしまうのですが
もう少し試行錯誤してみます。
いずれにせよ力づけられました。ホッとしています。
レスありがとうございました。
>>720 返すだけで戻り値を使ってないんじゃ、と消えるかもしれないな。
チェックもかねて、画面に値を出すようにすれば大丈夫じゃない?
(そこまでやっても、ただの定数に置き換えてしまうコンパイラとかあるかもしれない。)
最終的にはアセンブリを吐かせて確認するといい。
722 :
716:2005/07/07(木) 08:25:49
最適化無しで719さんの方法で15%ほど速く
>>721 もしかしたらtemplateだったせいかも知れないです。インライン化されていたのかな。
templateを外したらhogeも出ました
hoge: 5.579 ms
hage: 5.313 ms
(vc++6)
朝からお騒がせしました、お二人(三人?)に再度感謝です
その程度の処理だとlistは兎も角、vectorは普通の配列と全く同じ速度出るよ。
#つーか、gccでもVC++でもstlの有無で全く同じ(質の)コード吐くんだけどね。
>>723 VCだと
vector>=配列
になるときもない?(誤差範囲内だけど)
GCCは
vector使うと少し遅くなる気がした。
その辺は具体的なコードを提示して比較でもしない限りなんとも言えないなぁ。
そもそも最適化で消えないコードでって条件になっちゃうし。
vectorのiteratorは大抵の処理系/STL実装で非デバッグ時には単なるポインタだろ。
>>722 ちなみに std::list が double-linked list だということは知ってるよな
doubleじゃないSTLのlistを提示しない限りそのレスは無意味
そういえばslistは標準じゃないんだな。 STLPortにはあるけど。
次のようなコードがあるとします:
struct base1 { base1(int x) {}; };
struct base2 { base2(int x, int y) {}; };
// IF<P,T,F>クラステンプレートは、Pが非0のときT、0のときFをIF::typeにtypedefする
template <int N> struct derived : public IF<N,base1,base2>::type {};
このとき引数の数が異なるコンストラクタを持つ基底クラスをテンプレートで切り替え、
派生クラスのコンストラクタから、基底クラスのコンストラクタを呼び出したいのです:
derived<1> d(0); // base1から継承し、コンストラクタは引数1
derived<0> d(0, 1); // base2から継承し、コンストラクタは引数2
基底クラスのコンストラクタを呼び出すときには、派生クラスの初期化リストを使います。
ところが、派生クラスのコンストラクタ初期化リストでは、基底クラスのコンストラクタ
以外呼べませんから、次のように多重定義できません:
// Nが非0だとすると
derived(int x) : base1(x) {};
derived(int x, int y) : base2(x, y) {}; // error! 基底クラスはbase1
このように基底クラスをテンプレートで替える場合に、うまく派生クラスのコンストラクタの
引数の数を調整するようなテクニックがあれば、ご教示いただけると幸いです。
また、異なるアプローチもあればコメントください。
俺にはderivedをNの値によって特殊化する方法しか思いつかない。
試しにこう書いてみたら g++ 3.4.4 cygming special では通ったんだが。
derived(int x) : IF<N,base1,base2>::type(x) {}
derived(int x, int y) : IF<N,base1,base2>::type(x,y) {}
734 :
731:2005/07/09(土) 02:41:09
>>732-733 レスありがとうございました。
>733の方法で、パパ、うまくできそうです。
続きがんばります!
どうもネットの世界の「ご教示」とか「ご教授」って浮いた言葉だなぁ。
実は初めてこの構文を知ったんだけどさ
>
ttp://www.comeaucomputing.com/techtalk/templates/#esprobs >
>template <class T>
>T foo(T blah)
>{
> xyz object;
> T someInt;
>
>// (略)
>
> someInt = object.mt<int>(99.99); // AA: ill-formed
> someInt = object.template mt<int>(99.99); // BB: well-formed
>
> return someInt;
>}
ってなってて AA は ill-formed になってるんだけど、 object はテンプレートパラメータに依存してないんだから
template をつけなくても問題ないと思うんだけど。実際 g++ 3.4.4 だと通るし、. の前をテンプレートパラメータに
依存するように書き換えるとエラーが出る。
規格参照箇所 14.2-4
> When the name of a member template specialization appears after . or -> in a postfix-expression, or after
> nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a
> template-parameter (14.6.2), the member template name must be prefixed by the keyword template.
> Otherwise the name is assumed to name a non-template.
template <typename T>
class Hoge {
public:
typedef std::vector<T> Container;
typedef Container::iterator Iterator;
private:
Container v;
};
と書いて、Hoge<int> hoge; とか呼ぶと、implicitなtypenameだと警告を言われます。
iteratorを表現するにはどのように記述すべきなのでしょうか。
>>737 gcc version 3.2 20020927 (prerelease) です。
739 :
737:2005/07/10(日) 02:11:47
常識
当然
>>739 特殊化があるC++では、Tが確定しないと型推論が困っちゃうんで、
typedef typename Container::iterator Iterator;
って感じで。
typename Container::iterator Iterator;
も可能。
Container<int> v;
なら何とかなるはずだけど、explicitにtypenameしましょうという仕様。
>型推論が困っちゃう
そうなのか?
Tが確定しないと、特殊化のあるC++ではstd::vector<T>::iteratorが
typedefされた型名か、メンバ(メンバ変数・関数)かが分からないから
コンパイラへのヒントとして型名であることを明示するのを義務付けてるんでは?
745 :
デフォルトの名無しさん:2005/07/19(火) 22:11:08
全然わかってないけど質問します。
テンプレートクラスの実装って全てヘッダーでやらないといけないんですか?
.cppの方でやるとリンカーエラーが出てリンクできないのですが!?
(全部ヘッダーにコピペしたら通った)
追加
だが、しかしそれをやると2重定義になる…
どうすればいいんじゃーーーー
>>745 テンプレートの定義をcppファイルに書きたければ、宣言と定義の両方にexportを付けるだけ。
しかしほとんどのコンパイラで使えない。(使えるコンパイラが全くないわけではない)
というわけで普通はヘッダにインラインで全て書く。
ごく稀に明示的実体化が使われることはあるが。
>>747 明示的実体化ってまさか、
template class c<bool>;
template class c<char>;
template class c<unsigned char>;
みたいに延々と cpp ファイルに書いていくわけ?
g++にはextern templateってのがあるね。
>748
そゆこと。
751 :
745:2005/07/19(火) 23:17:21
やってみた
>>747 make -k all
g++ -Wall main.cpp Class.cpp -c
g++ -Wall main.o Class.o -o a.exe
main.o(.text+0x25):main.cpp: undefined reference to `Class<int>::Class[in-charge]()'
collect2: ld returned 1 exit status
make: *** [all] Error 1
ムリポ
>>749を含めて出直してくる。これはイマの私の頭ではいくら考えても答えが出ない。
本を読むかg++のマニュアルを漁るか…
>>751 g++のinclude/bits/istream.tccより
// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
// NB: This syntax is a GNU extension.
#if _GLIBCPP_EXTERN_TEMPLATE
extern template class basic_istream<char>;
extern template istream& ws(istream&);
extern template istream& operator>>(istream&, char&);
extern template istream& operator>>(istream&, char*)
template <class T> class foo;
template <class T> class baa{
friend foo;
int n;
public:
baa() : n(777){}
};
template <class T> class foo : public baa<T>{
int hoge;
public:
void set_val( baa<T>& arg ){ hoge = arg.n; }
};
int main(){
baa<int> b;
foo<int> f;
f.set_val( b );
return 0;
}
インデントが全角スペースですいません
これだとarg.nにアクセス出来ないのですが、間違っている場所を教えて頂けないでしょうか
friend foo; が、やっぱり
template <class T> friend foo; なんでしょうか
>>753 g++ でコンパイルすると、
:4: error: ISO C++ forbids declaration of `foo' with no type
:4: error: `foo' is neither function nor member function; cannot be declared friend
まぁそれは置いとくとして、
friend class foo<T>;
で通ったよ。
755 :
753:2005/07/23(土) 19:59:42
>>754 やっぱりclass指定しますよね
書き込む前にチェックしたサイトで、指定が無かったので、自分が間違っていたのかと
そうか、再度template <class T>付けるのは馬鹿でした。
VC6なので、Tが同じじゃなかったらアウトだったかも・・・良かった。
本当に助かりました。コンパイルまでして頂いてすいません。ありがとうございました。
baaっての…なんかプログラムがアホっぽくなるな。
>>755 friend かどうかっていう問題なのか?
baa<T>::n が private か protected/public かどうかっていう問題では?
>>757 vtableを避けるための小細工なんです
眉をしかめる人が多いと思いますが、自分しか使わないのでお見逃しを
>>758 よくわからないな。
>>753 のを
template <class T> class baa{
protected:
int n;
public:
baa() : n(777){}
};
とすると VC6 だと vtable に関して状況が変わるの?
753がprotectedを知らなかったというオチ?
>>759 失礼、深読みしすぎてました。
しかしすいません、そうなると
>>757で頂いたレスの意図が分からないです。
protectedすると、引数で他のbaaを受け取ったとき、nにアクセス出来るのでしょうか。
762 :
760:2005/07/24(日) 00:40:00
753のコードでは、bar<T>::nがprotectedならfoo<T>::set_valの中でarg.nにアクセスできると思っていたがそうではなかったようだ。
スマソ
>>761 アクセスできると思ってた。けど間違ってたのなら失礼。
・基本 class から 派生 class を public 継承したとき、
・基本 class の protected member である n について、
・派生 class から this の n にアクセスできる。
・派生 class から this 以外の n にアクセスできない。
ということかな?も一回勉強しなおそ。
・ある class の private member である n について、
・その class から this の n にアクセスできる。
・その class から this 以外の n にアクセスできる。
というのは間違いないと思うんだけど。
あと自分の VC7 は、これに関して template class かそうでないかによって
コンパイル結果が違うのもよくわからない。
勉強しなおした。
>>763は間違い多数につきスルーよろしく。失礼しますた。
Compile-time if
で型でなく値を返すにはどうすればいいのでしょうか?
int v= boost::mpl::if_c< (sizeof(T) <= sizeof(double)), 10, 20 >::Value
はだめでした
>>765 boost::mpl::int_
を使って、型にマップすればいい。
>>765 struct R0 {
enum {value = 10};
};
struct R1 {
enum {value = 20};
};
template <typename T>
int func ()
{
typedef typename boost::mpl::if_c <(sizeof (T) <= sizeof (double)), R0, R1>::type Result;
return Result::value;
}
template<CONTANER>
class CmyContaner
{
typedef CONTANER::iterator iterator_type;
};
としたらコンパイル通らなかったんですが、
CONTANER::iteratorはできないってことなのでしょうか?
>>768 -typedef CONTANER::iterator iterator_type;
+typedef typename CONTANER::iterator iterator_type;
そのままじゃ型名かメンバ変数かわからんからね。
> CONTANER
北斗の拳の主題歌を思い出すスペルミスだな。
>>768 ここもだね
-template<CONTANER>
+template<typename CONTANER>
772 :
デフォルトの名無しさん:2005/07/30(土) 08:40:48
template<Functor>
class MyMethod
{
public:
Functor f_
MyMethod(Functor f):f(f_)
{}
value()
{
f_(10);
}
};
class MyClass
{
public:
struct MyFunctor{
operator()(int a)
{
std::cout << a;
}myFunc;
//MyMethod<MyFunctor> myMethod(myFunc);//コンパイル通らない
MyMethod<MyFunctor> myMethod(MyFunctor);//なぜかコンパイル通る
value(){
myMethod.value();//左側がクラス 構造体 共用体でありません と怒られる
}
};
クラスの中でfunctorを定義したら動かなくなりました。
回避方法はないのでしょうか?
>>772 >クラスの中でfunctorを定義したら動かなくなりました。
クラスの外でfunctorを定義したらそれ動く?
>772
とりあえず } が 1 個足りない。
} myFunc; の前に 1 個ある、でいいのか?
>MyMethod<MyFunctor> myMethod(MyFunctor);
これだと MyFunctor 型の引数をとり、MyMethod<MyFunctor> 型を返すメンバ関数 myMethod を
宣言しているんじゃまいか?
>//MyMethod<MyFunctor> myMethod(myFunc);//コンパイル通らない
なんでメンバ変数を宣言してるのに初期化しようとしてるの?
MyMethod<MyFunctor> myMethod;
MyClass() : myMethod(myFunc) {}
じゃねーのか?あと↑だと myFunc との初期化順序が問題になる場合があるかも。
今回の場合、MyClass() : myMethod(MyFunctor()) でいいような気もするが。
775 :
772:2005/07/30(土) 14:59:26
すみません } が1つぬけてました。
template<Functor> class MyMethod
にclass の外で定義したfunctorを使うと
意図したとうりの動きをすることを確認しています。
>>775 >class の外で定義したfunctorを使うと
>意図したとうりの動きをすることを確認しています。
本当に?
コピペにかなりミスがあると思うよ
MyMethod::value()
MyClass::MyFunctor::operator()(int a)
の返値の型は?
もし本当に動くなら処理系を教えてね
777 :
776:2005/07/30(土) 15:09:07
たぶんこんなことしたいのかな
template <typename Functor>
struct MyMethod {
Functor f_;
MyMethod (Functor f): f_(f) {}
void value () {f_ (10);}
};
struct MyClass {
struct MyFunctor {
void operator () (int a) {
std::cout << a;
}
} myFunc;
MyMethod <MyFunctor> myMethod;
MyClass (): myFunc (), myMethod(myFunc) {}
void value() {myMethod.value();}
};
template<X>
class CHoge
{public:
CHoge( X= typeof(x) ) {}
};
なんてできないの?
自動で型判別してほしい。
自動判別した型を使ってCompile-time Ifもできるとさらにいいんだけど
>>778 >自動で型判別してほしい。
>自動判別した型を使ってCompile-time Ifもできるとさらにいいんだけど
これらはできるけど
例で何がしたいのかさっぱり分かりません
template< ArrayType >
function( ArrayType array)
{
Compile-time If (ArrayType はポインタの配列?)
{
int a= array[0]->value;
}else{
int a= array[0].value;
}
こんなことがしたい
type_traitsでいいんじゃないの?
個人的には値の配列とポインタの配列を静的多相に扱おうとする行為そのものに
異議を申し立てたい.
次のようなコードが、Visual C++では通るけどGCCでは通りません。
オブジェクトの名前と番号の型を保持する構造体を用意
template<class S,class I>
struct Types
{
typedef S String;
typedef I Integer;
};
この定義を受け取って型を定義するベースクラスを作成
template<class T>
struct Base
{
typedef typename T::String StringType;
typedef typename T::Integer IntegerType;
};
そして、これを利用するサブクラスを作成。
template<class T>
struct Derived : public Base<T>
{
StringType name; //!< ここでコンパイルエラー
IntegerType number; //!< 同様
};
typedef Types<std::string,int> StdTypes;
Derived<StdTypes> derived;
続き
以下のように書けばGCCでもコンパイルは通ります。
typename Derived::StringType name;
typename Derived::IntegerType number;
こんな面倒な書き方しかできないなら、
わざわざベースクラスにtypedefした意味がないんですが
何かいい方法ありませんか?
>>783-784 Base の定義中に typename が必要な理由を知っていれば、無理だと予想が付くだろうに。
>>783-784 俺だったら
Base::Stringと書けないか
Derivedの中にusing Base::String;と書けばStringが使えないか
の2つをまず試してみる。これでできるかどうかはもちろんしらんが。
Baseを使うなら、
typename Base<T>::StringType name;
typename Base<T>::IntegerType number;
こうなるから、これこそ、
> わざわざベースクラスにtypedefした意味がない
ので、
>>784のやり方が良いだろう。
VC++もそのうち
>>783は駄目になることでしょう。
>>784 それVC7.1のバグらしい。
面倒見が良すぎて、typenameを本来ならば書かなければならない
所を、曖昧さがない場合は無くても通してしまう。
VC7.1でもちゃんと typename は書くべき。
このスレの難読コードをみて
おれにとて
C++はなかたことになた
そんなだから、未だに君にとってこの程度が「難読コード」なんだよ。
俺もtemplateのコードは可読性が低いと思うよ
唯一の弱点だな
テンプレートとC++「本体」って明らかに別の言語だよな。
概念の異なる2つの言語が混在してるんだから、
可読性が低いのは当たり前。
構文の話なのかな。
>>784 template<class T>
struct Derived : public Base<T>
{
typedef Base <T> Base_;
typedef typename Base_::StringType StringType;
typedef typename Base_::IntegerType IntegerType;
StringType name;
IntegerType number;
};
797 :
神゜:2005/08/06(土) 20:49:53
そろそろ俺の出番か?
>>784 ベースクラスがテンプレート依存でなければ StringType,IntegerType
は見えるが、そうでない場合は 795 のように書く必要がある。
実はずっと前の GCC で VC7.1 みたくエラーにならない時期が
あったんだが、バージョン上げたらエラーになったんで仕様を
確認したことがあったのを思い出したよ。
template<class A>
struct Foo
{
template<class B>
struct Bar
{
};
};
このBarだけを特殊化するのって、GCCでは
template<>template<>
struct Foo<int>::Bar<int>
って書かなきゃならないんだね。
VC++7.1では
template<>
struct Foo<int>::Bar<int>
で通るんだけど、これはバグなのかな?
>>800 14.7.3.17 より
"If the declaration of an explicit specialization for such a member appears in namespace scope, the member declaration shall be preceded by a template<> for each enclosing class template that is explicitly specialized."
template<> template<> ... と繰り返すのが正解っぽい。
>>800 gccのバージョンは何?
g++ 3.3.5
だとそれ両方とも通るんだけど
新しいのは通らないのかな?
template <class T>
typename enable_if<boost::is_integral<T>, void>::type
foo(T t) {}
で関数を定義したりできないのはわかるけど
これでclassのコンストラクターを定義したりしなかったりを決めると
コンストラクターに戻り値が定義されています
と怒られる。何か方法ないのでしょうか?
template <class T>
class A{
typename enable_if<boost::is_integral<T>, void>::type
A(T t) { }
}
>>805 SFINAEは戻り値の型でやる方法と(デフォルト)引数の型でやる方法の2通りできて,
コンストラクタの場合は戻り値の型を指定できないですから引数の型のほうでやります.
template<class T>
class T{
A(T t, typename enable_if<boost::is_integral<T> >::type * = 0){}
};
こんな感じで.逆に演算子関数の場合は余計なデフォルト引数を指定できないので
戻り値型で,という感じになると思います.
enable_ifが何をするもんなのか、未だにわかんねえ。
てか、何年英語の勉強してもboostのドキュメントさえ読めない俺ってすげえよ。
よっぽど英語の才能が無いんだな。
テメェは自己紹介がしたいだけだろ
分からねぇんだったらイチイチ出てくんな
>>807 SFINAEによるオーバーロードセットのコントロールを簡単に
行うためのユーティリティ。
英語分からなくてもC++分かるんならひたすらソース詠めば
何となく見えてくる、かもよ。
>>808 なにキレてんのキミ。
相手以上の駄レス書いてたら意味無いのに。
駄レスとかいってたら、ほとんどがそうだろw
ほとんどがそうならなおのこと
突然特定のレスにキレる理由が無いよ。
自己顕示欲丸出しの厨房がウザイだけだろ
まあ、どこにでもいるからいちいちキレるのもどうかと思うが
キレて説教するほうがよっぽど自己顕示欲激しいと思う。
世に言う自爆ですな。アホくさ。
説教がどう自己顕示欲につながるんだ??
817 :
デフォルトの名無しさん:2005/08/07(日) 23:22:14
>>816 キレるたびにいちいちスレ違いの書き込みするような奴が
自己顕示欲薄いって言い張る気?
819 :
デフォルトの名無しさん:2005/08/07(日) 23:30:34
enable_ifがわからんってののどこが自己顕示欲に繋がるのかもわからんけどな
820 :
デフォルトの名無しさん:2005/08/07(日) 23:30:49
>>818 藻前もキレてるじゃん
あと煽り耐性なさ過ぎ
いい加減スルーしろよ
>>815 いや,そこの部分は別に何かが問題だなんて書いてないです.
単にSFINAEというのがどう機能するか(そしてなぜそのような機能が必要なのか)
を説明しているだけです.
816が煽りには見えないけどなあ。
普通にズレてるだけで。
>>815 あっと,「もしSFINAEがなければこういうことが問題だよね」というのは書いてますけれど.
824 :
デフォルトの名無しさん:2005/08/07(日) 23:35:03
本日の推奨NG
「。」「顕示」「煽り」「キレ」
すっきりして(・∀・)イイ!!
expressional template
VC.net2003だと、ちょっと複雑な式を書いただけで
コンパイル通らない。
そういうものなの?
gccなら通るのかな
>>826 その「ちょっと複雑な式」とやらを晒すとレスが付くかもしれない。
828 :
デフォルトの名無しさん:2005/08/08(月) 03:35:21
>>826 現存する如何なるコンパイラでも通らない程複雑(広義の)なコードに問題ありに100円。
ネストが17超えるとか?
いろんな要素が混じってるので必ずしもexpressional templateが
原因でないのかもしれないけど
boost::numeric::ublas::matrix & A(){return A_ }
boost::numeric::ublas::matrix & B(){return B_ }
B() = prod( A(), A())*3 + B() + ....
こんな感じかな.全部はさらせないのですまそ
>>830 エラー貼ったがいいよ
もし膨大なら
再現するコンパイル可能な最小のコードを貼って
832 :
831:2005/08/09(火) 01:45:25
>コンパイル可能な
おっとコンパイルは通らないのか
>あなたがコンパイル通らないことを理不尽に思う
に訂正
ようするにテストする側の身になってコードを
貼ってください
>>830 >こんな感じかな.全部はさらせないのですまそ
じゃあ、他の人にエラーの原因を調べてもらうのも諦める事ですな。
証拠不十分なまま、証言台に立つような物ですぞ。
だれもいない
ホントにだれもいないのかよ
836 :
デフォルトの名無しさん:2005/08/20(土) 20:39:26
いねーよ
質問やら話題があれば人は自然と集まってくる。
おまえら
”てんぷれーと”にだまされてないか?
”しーぷらぷらのてんぷれーと”って結局あれだよ。
中途半端。
そう中途半端。
LISPに比べたら。
全然読み易くならない。
いろんな括弧であふれてLISPの方がまだサルのように読みやすい。
まあここにタムロしてるおまえらの言い分は判ってるよ
こうだろ、静的カタカタ型が重要なんです!
LISPじゃすぴーどでないよプププ
とかな。
ばーか。
カタなんかより柔軟性なんだよこのご時世はよ
カタカタうるせーのなんのって、笑うわ。
C++考えた奴みたいにハゲろ
全員
確かに、「ネイティブコード吐く言語じゃないと速度が」
とか必死に言ってる奴に優秀なプログラマはいないな。
しーぷらぷらの処理系。
てんぷれーとバグだらけ。
笑うわ。
いったい何年てんぷれーとやってんだよ
おまえらがべんだーの修正待つあいだに
おれLISPで新しいマクロどっさり作る
生産性バカたけぇーわLISPはよ
LISPはカタないからすぴーどでないよプププて、
そりゃ頭がかてえ証拠だな。
そんな奴は引退したほーがいいんじゃねーかなあ
LISPにカタないなら組み込めよ、ハゲども
ぶーとすとらっぷとか考えろよ
わかるか?ぶーとすとらっぷって。
しーぷらぷらにはそんながいねんはないかもなあ。
最適化なんかやりやすいなーすいすいいけるぜ
こんすの海の中にいると不満なんてすぐ解消する
それがLISP。
まあ頭のかたいカタカタ野郎は
やっぱりC++考えた奴みたいにハゲろ
全員
C++をしーぷらぷらなんて言うのは無能。
C++でLisp系の俺言語&処理系作るのが最近の俺の趣味なんだが、
なんかこいつの仲間と思われたくないな、恥ずかしくて。
>>842 シープラスプラス?
それともシーたすたす?
しーいんくりめんと
C++
後置ということは、まだ本当のC++にはであてないわけだ
C++には出会えている
++Cに出会えてないだけ
838は、C++のテンプレートが読みにくく、
コンパイラのバグのことも分かっていて、
C++作った人物についても詳しいようだな
Schemeの純粋指向にはあこがれるけど、Lispはどうでもいいや。
継続は面白いな。
>LISPはカタないからすぴーどでないよプププて、
型が無いと遅くなるつうのは初耳ですが、どこの情報?
>>849 VBのバリアント型みたくデータ側に型情報があるから
オブジェクトを参照するたびに動的な判定が毎回必要ってことだよ。
型判定に値の取り出しとか最低でもCの3倍以上のコストが掛かる。
Rubyが遅いのもこれがかなり影響してる。
でも日本語は不自由なようだ。
852 :
851:2005/08/21(日) 01:09:45
> オブジェクトを参照するたびに動的な判定が毎回必要ってことだよ。
随分ダサい実装ですね。
そのダサイ実装を越えたところに桃源郷が
ももげんごう?
ももげんごう(←なか変換できない)
桃源郷=Xanadu キサナドゥ
>>850 正直、有名なコンパイラならそんなださい実装は少ないよ。
Common Lispには型指定の構文があるくらいだし。
数値計算したい人は
速度気にしないならlistでなくてMatlab使う
だれもいないからとか言うから
人稲杉なので、チラシの裏
boost::bind は、bind( f, _1, _2, a, b, _1 ) を行うことで、
func::return_type ( A1 & a1, A2 & a2 ) というファンクタを返すけど、
この _1 や _2 を、_decimal や、_text、_float のような書式指定プレイスホルダに
置き換えて、以下のようにすれば、タイプセーフな printf が出来るなと
考えたことがあった。
function< void( int ) > f = format( cout, "a = ", _hex, endl );
// ↑ cout << "a=" << %x << endl; と同じ事を行うファンクタを返す。
f( 10 ); // cout << "a=" << hex << 10 << endl;
f("aaa"); // コンパイルエラー
上の形とは違うけどその思想に基づいて実際に作ってみたことがある。
でも結局実用では (w)sprintf しか使わなかった。勉強にはなったけどね。
template プログラミングは楽しいけど、冷静なるとしなくていいことまで
テンプレート化してたりしていることがあるので気をつけないと。
>>862 > 冷静なるとしなくていいことまでテンプレート化してたりしていることがある
昨夜、そんな関数テンプレートを必死で非テンプレート関数に直してた・・・。
数日前に必死で関数テンプレートにした箇所だったのだけど・・・。
template<typename X_TYPE>
void xxx(X_TYPE x)
{}
として型の自動認識の手間減らしは多用するな
そうね。時々やる。いっそのこと型を書くのはオプションにして
MLみたいに型推論してくれればいいのにと思う。
C++ 0xだとそんな機能が追加されるとかされないとか。
867 :
デフォルトの名無しさん:2005/08/28(日) 09:36:27
テンプレートがちんぷんかんぷんでまったく理解できない私に
理解できるようになる方法を教えてください。まじで。
引数の型を使うときに決められるんだよ。
>>867 騙されたと思ってstd::min()でも使って味噌。
せめてstd::vector くらい使わないとありがたみ沸かないだろう。
>>867 つ[C++ Templates(英文)]
STL バンザイ
STLとboostが無かったら俺C++使いつづけて無かったよ。
俺もそうだ。
会社でtemplate使うなって言われたんだけど…
何故?
会社で使いこなせるヤシがいないからと邪推
代わりにLISP使え
もっと困るかもな
へへ
お前だけは使うなって言われたなら
そうかもしれないけどさ
>>881 なんでそんな必死にこの話題にフタしたがるの?
コンプレックスでも刺激された?w
VC6のプログラム保守してるとかじゃないのか>875
>>883 大丈夫だよ。
質問に答えられない誰かさんの頭は大丈夫じゃないみたいだけど。
・移植性重視
・扱える開発者が少ない or メンテする人が固定とは限らない
のどっちかだろうねえ
後者の事情のほうが多いと思うけども
管理職の団塊世代が、ピュアなC以外理解できないとか
名前空間→記述が冗長すぎる
テンプレート→制限が多すぎる
クラス→継承が可読性を悪化させる
その他→コンパイル時間が長すぎる
C++→俺が解からない
俺が解からない→みんなも解からない
>>886 >移植性重視
templateって移植性下がるの?
例えばGCCと心中するつもりならGCCで動けばOKって人もいるでしょ
>>891 ある程度ISO C++に準拠したコンパイラがない環境には移植できなったりだとか。
少なくとも、vc7.1とgccの両方で動くテンプレートくらい書けないと
話にならないと思うけど。
VC7.1とgcc3.3以降で動くテンプレート書くのは簡単だろ、どっちもほぼ100%標準準拠なんだから。
むしろVC6とかgcc3.2とかで動くか動かないか判断する方が難しいと思われ。
>>895 VC6とgcc3.2以前はもうあきらめた。
というかエラーメッセージすらとんちんかんな時があるのが頭痛い。
昔の仕事のプロジェクトコードのメンテでちょっとしたテンプレート書いてとかで
引っかかると泣きたくなる。
>>894-895 まるで、複数コンパイラで有効なテンプレートを書くのが上級者であるかのような言い方だな。
そういった汎用性のあるテンプレートは入門者レベルの機能しか使ってない。
君らは、入門者レベルのテンプレートしか書いたことないんだろ?
スレの存在を否定するような行為が、目下のベストな対処法
「技巧に走らない」
>>897 > であるかのような言い方だな。
印象だけでものを書く場合、その印象がトンチンカンだと
残りの文章がすべてトンチンカンになるから今後は気をつけな。
シンプル伊豆ベスト
>>897 「入門者レベル」とか「汎用性のある」とか、
自分が「上級者」じゃない事がバレバレなんですがw
まぁ、恥の上塗りだけはしないようになw
902 :
名無しさん@そうだ選挙に行こう:2005/09/10(土) 18:43:40
>>888 つまり、templateに限らずC++は糞だって事で包茎?
ていうかお前が包茎。
24時間テレビ C++ は地球を救う
894は、VC以外でも通るように、typenameちゃんと書けとか
その程度の意味じゃねえの?
言語仕様が複雑すぎて処理系が追いつかないのは本末転倒
言語仕様満たしてから最適化とかやれよ馬鹿ベンダーはよ
現実逃避してんじゃねーよ
909 :
名無しさん@そうだ選挙に行こう:2005/09/11(日) 07:05:25
ヒント:需要と供給
つまりDelphiが最強ということになるな。
Delphi知らないんだけどtemplateみたいなのあるの?
あるか!
なぜ怒る・・・。
そこがDelphi信者のコンプレックスなのか?
でもDelphiってすごいよね
一代でここまでメジャーになった言語パッケージってないでしょ
それともPascalの下積みがあったから?
>>914 世間ではC#の方がメジャーだと思うがね。
C#は単なるM$の宣伝力だと思うけど
>>916 CとかC++から名前の連続性もあるしね。
C#なんて使って製品開発とかしてる香具師っているの?
天下のM$がVBで真似したぐらいだからな
当時はRADは斬新な開発環境だった
Delphi使いこそプログラマの頂点ということか。
Delphiが当初からMS謹製であったならば、VBだ、MFCだ、ATLだ、WTLだ、
STLだ、.Netだ、C#だ、C++/CLIだといったことで右往左往することもなく
10年間一貫とした言語体制、RAD環境、爆速コンパイル、コンポーネント化
による高い生産性等々を皆が維持・共有できたかと思うと残念でならないよ。
C#って、Delphi作った香具師が理想の言語として設計したんだろ。
Delphi信者御苦労様w
まだDel厨いたのか
そろそろ博物館に行けよ
博物館の恐竜が一緒に浮かれて踊ったぜ
予想通り嫌Del厨が暴れることになったか・・・
つか、スレ違いうぜぇですよ?
929 :
デフォルトの名無しさん:2005/09/14(水) 15:45:52
template< typename char_type, tepename char_traits >
std::basic_ostream< char_type, char_traits >& operator<< ( std::basic_ostream< char_type, char_traits >& stream, const int& value )
{
stream << "value = " << value << endl;
return stream;
}
この関数内で文字列リテラル"value = "を
char_type がcharなら、"value = "
char_type がwcharなら、L"value = "
にしたいんですが、どうしたら良いでしょうか?
>>929 テンプレートの特殊化か、オーバーライドで解決させる。
ex)
inline char const * choice( char const * s, wchar_t const *, char )
{
return s;
}
inline wchar_t const * choice( char const *, wchar_t const * s, wchar_t )
{
return s;
}
stream << choice("value=",L"value=",char_type()) << value << endl;
931 :
929:2005/09/14(水) 16:31:48
>>930 #define literal_str( char_type, str ) choice( str, L##str, char_type##() )
付きで採用しますた。
ありがとうございました。
933 :
929:2005/09/14(水) 21:31:05
だからなんだよこのタコ助!
確かに余計だな。
935 :
929:2005/09/15(木) 00:04:09
>>933 >>929の著作権は私にあります。
なんなら出るとこ出ても・・
と思いましたがきっと
>>933は
私にインスパイヤされて誕生した新種なんでしょう。
今回はかんべんしてやります。
template <class T>
void f1(T t)
{
f2(t);
}
void f2(int) {}
int main()
{
f1(1);
}
というコードは正しいのでしょうか?
VC7.1 ではコンパイル可能で comeau ではコンパイルできません。
>>936 comeauだとなんてエラーが出るの?
938 :
636:2005/09/15(木) 13:09:16
>>637 identifier "f2" is undefined
detected during instantiation of "void f1(T) [with T=int]"
というエラーです。strict mode のみのようです。
ちなみに、ユーザ定義型の場合は期待通りにコンパイルできました。
template <class T>
void f1(T t)
{
f2(t);
}
struct a{};
void f2(a) {}
namespace adl
{
struct a{};
void f2(a) {}
}
int main()
{
f1(a());
f1(adl::a());
}
このコードはコンパイル成功。
>>936 gcc3.4.4(MinGW) で、-Wallで通る。
>>938 f2()のプロトタイプ宣言が必要っぽい。
Incompatibilities Between ISO C and ISO C++, David R. Tribble
http://david.tribble.com/text/cdiffs.htm#C90-impl-func ・ Implicit function declarations
> C++ does not allow implicit function declarations. It is invalid to call a function
> that does not have a previous declaration in scope.
>
> C99 no longer allows functions to be implicitly declared.
> The code above is invalid in both C99 and C++.
>>936 標準の (14.6.4.2/1) をそのまま読む限りでは, unqualified name lookup として
解決される名前は point of definition の文脈のみが考慮されて,
associated namespaces を用いた名前解決(要するにADL)では,point of definitionと
point of instantiation の双方の文脈が考慮されるみたいですね.なので,
>>936 の f1(1) という呼び出しにおける f1 中の f2(t) に対する名前解決の場合,
unqualified name lookup では f2 の呼び出しを定義している場所(point of definition)
からは f2 という名前は解決されないので失敗し,さらに f2(t) は int を引数とした
呼び出しのために associated sets of namespaces and classes も空 (3.4.2/2) の
ため,ADL 経由でも f2 は見つからずに,結果 f2(t) という関数呼び出しに対応する
名前の解決が失敗する.
一方で,
>>938 の f1(a()) 及び f1(adl::a()) という呼び出しにおける f1 中の f2(t)
に対する名前解決の場合,
>>936 と同様 unqualified name lookup による名前解決は
失敗する.ところが,a 及び adl::a はユーザ定義型で,各々グローバルと adl が
associated namespace になる.この場合,f2(t) という呼び出しが定義されている
場所 (point of definition) と f1 がインスタンス化された場所
(point of instantiation) 双方の文脈が名前解決において考慮される.結果,
point of instantiation の文脈で void f2(a) と void adl::f2(adl::a) が
visible のため,これらの名前解決が成功する.
と,こういう感じだと思います.ちなみに VC++7.1 の挙動は,dependent name だろうが
non-dependent name だろうが,ADL 経由だろうがなかろうが,全て
point of instantiation の文脈も考慮するという実装になっているための結果で,
これは標準に準拠した挙動ではないです.
944 :
943:2005/09/15(木) 17:49:27
あ,すいません.長々と書きましたけれど結論としては,
936のコードは(標準に準拠していないという意味で)正しくないと思います.
945 :
936:2005/09/15(木) 22:07:49
>>943 なるほど。
実体化の時点で名前の解決を行っても、
実体化の時点の文脈が考慮されるとは限らないんですね。
皆様、ありがとうございました。
template<class T>
class Foo {
public:
...;
private:
class Bar {
public:
...;
bool operator()(const Bar& l, const Bar&r) const;
private:
T m_value;
int misc_info;
};
std::multiset<Bar, Bar::Comp> m_bars;
};
m_bars の先頭・末尾に番人(misc_value などは他のメ
ンバと同様にアクセス可能にしたもの)を導入したいの
ですが、どういうアプローチで作れば良いでしょうか?
>>946 undeclared identifier `misc_value'
STLportではコンパイルできるけれど、
g++のSTLではエラーが出てしまうようなコードってどんなものがあるでしょうか?
vectorやstringくらいしか使ってないんですが、コンパイルでエラーが出ます。。
エラーメッセージ書かん奴には答えない
template<int num, int count> struct power{ enum { value = power<num, count-1>::value * num }; };
template<int num> struct power<num, 1>{ enum { value = num }; };
template<int num> struct power<num, 0>{ enum { value = 0 }; };
template<> struct power<0, 0>{ enum { value = 0 }; };
∋oノハヽo∈
( ´D`) <テンプレート ♪ で、計算♪計算♪ age♪ age♪
(つ┳9
(_)┃_)
━§━
§
⌒ヽ〃⌒ヽ〃
int main()
{ //2の8乗
cout << power<2, 8>::value << endl;
return 0;
}
>template<int num> struct power<num, 0>{ enum { value = 0 }; };
それはどうかと思うぞ。
template<int num> struct power<num, 0>{ enum { value = 1 };};
<0,0>,<num,1>の特殊化は必要ないな
むしろこうしてコンパイル時エラーにしろよ。
template<> struct power<0, 0>{};
0^0って数学的にはどうなるの?
スマン。レス番間違えた orz
>>957-958 一方で0 ^ n = 0となっているから問題になる。
ところで^と言えばXORの立場が。
VC6のtemplate関数ってバグある気がするんだけど...
template<typename T> void test();
引数無し呼んだときに解決できてないみたい...
template<typename T> void test(const T&);
みたいにすればオーバーロードで解決できるのか、大丈夫みたいなんだが...
いまどきそんな化石コンパイラに文句言われても…
化石以前にtemplateに関しては欠陥コンパイラですから・・・
そもそもC++コンパイラじゃないですから
少なくともANSI/ISO C++準拠とは言えないな。
じゃーVC7はどうですか?
7.1はかなりまとも。
7と7.1は全然違うぞ
7はかなり微妙
7はCStringにバグがあったね。STL周りもちょっと不安定なところがあった気もする。
7.1って具体的にclのどのバージョン?
今
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
っての使ってるけど
VS.net(VC.net)2003か、VCTK2003のやつが7.1
13.10.3077なら7.1だな。VS.net2003の方のやつだろ。
codeguruに記事の投稿してみたがレビュー通んないとだめなんだね
973 :
デフォルトの名無しさん:2005/10/18(火) 15:57:25
age
人稲杉なので、バカネタを投下。
http://www.hakusi.com/up/src/up5538.zip.html Boost.Lambda みたいに Expression Template を使った、引数に対して安全なフォーマットライブラリ。
Boost.Function や、Boost.Bind と組み合わせることが可能。
以前作成したものと違い、オマケ機能だが入力も可能で、ワイド文字にも対応。
ただ、 _ と % だらけで見た目がキモイ上に、実用性がイマイチ謎。
Expression Template の資料として。
// 出力
string strA, strB;
sprint( strA, "1 " % !_x[6] % "/" % _s, 10, "aaaa" ); // sprintf( str, "%#6x/%s", 10, "aaaa" ); みたいな。
sprint( strB, "2 " % (!_x[6]*='0') % "/" %_s, 10, "aaaa" ); // sprintf( str, "%#06x", 10, "aaaa" ); みたいな。
cout << strA << endl; // 1 0xa/aaaa と出力
cout << strB << endl; // 2 0x000a/aaaa と出力
// 入力
int xA, xB;
string yA, yB;
sscan( strA, "1 " % _ws % _x % "/" % _s, xA, yA ); // 空白部分はスキップさせる
sscan( strB, "2 " % _x % "/" % _s[3], xB, yB ); // 文字列部分は3文字のみ取得
// 出力
print( cout, "xA = " % _d % "\nyA = " % _s % _endl, xA, yA );
print( cout, "xB = " % _d % "\nyB = " % _s % _endl, xB, yB );
// xA = 10
// yA = aaaa
// xB = 10
// yB = aaa と出力
難読コンテスト会場はここですか?
977 :
デフォルトの名無しさん:2005/10/31(月) 13:08:43
>>974 すげー--w
確かに scanf っぽいこと出来るし。
でも、Perl みたいで汚いな。使おうとは思わんけど。
>>975 boostな人達はあれば便利だけど、一般人的にはどうなのかなあ?