05/02/18 21:23:27
>>329
URLリンク(boost.cppll.jp)
の2番目を。
332:デフォルトの名無しさん
05/02/18 23:38:55
>>330
C++ ってそういうもんだよ。人によって用途も違えば、実行環境のリッチさも
天と地ほど違うので。
333:デフォルトの名無しさん
05/02/22 15:00:52
新規にクラスを作るならば、COM のように侵入型の参照ポインタにして、
intrusive_ptr で管理するとか
334:デフォルトの名無しさん
05/02/22 17:27:12
STLかboostあたりに、ある条件を満たすものをoutput_iteratorにコピー
するような関数はないでしょうか?
boost::mplにcopy_ifというそれらしい名前のがあるんですが、
使い方がさっぱりわからない……
335:デフォルトの名無しさん
05/02/22 17:40:29
なぜか std に copy_if ないんだよね・・・
boost::filter_iterator と std::copy でなんとか汁
336:デフォルトの名無しさん
05/02/22 17:43:19
std::remove_copy_if(first, last, std::not1(pred));
337:336
05/02/22 17:43:58
ごめん。
std::remove_copy_if(first, last, out, std::not1(pred);
だ。
338:デフォルトの名無しさん
05/02/22 18:06:02
今回は元のコンテナを変更したくないので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も説明がよくわからんのですよね。
削除するのに大きさが変わらないってどういうこと?
339:デフォルトの名無しさん
05/02/22 18:06:58
>>338
remove_copy_ifは入力シーケンスを変更しないよ。
340:デフォルトの名無しさん
05/02/22 18:17:58
>>338
return result;
341:一つ賢くなった!
05/02/22 18:32:43
>>339
おお、本当だ。コードを見るとほぼそっくりではないですか。
今までremove_copy_ifは元のを破壊的に変更しつつ、削除したものを
コピーするのだと思っておりました。
名前がミスリーディングだと思うのです……。
>>340
忘れてました。というか気にしてなかったのですが、返すべきですね。
342:デフォルトの名無しさん
05/02/22 19:24:56
struct NURUPO
{
template<typename T> operator T*() { return 0; }
};
int ILoveNurupo()
{
NURUPO mynurupo;
return (int)mynurupo[0];
}
vc7.1とgcc3.3にガッ
343:デフォルトの名無しさん
05/02/22 21:10:19
なんか違わないか?
344:デフォルトの名無しさん
05/02/23 01:38:28
>>338
STLPortには入ってるよ。
345:デフォルトの名無しさん
05/02/24 14:00:35
テンプレートの特殊化ってどこに書きますか?
以下のように特殊化する型の定義と一緒に書くと、
* 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();
346:345
05/02/24 14:01:58
* 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 のヘッダファイルに書き足すわけにもいけませんし・・・。
347:デフォルトの名無しさん
05/02/25 00:39:40
>>345
URLリンク(www.kuzbass.ru)
14.7.3 -6- および -7- で、
使う場所より前に特殊化は宣言されていないといけない、
というルールは書いてあるが、コンパイラによるチェックは不要ということになっている。
あげくに規格中に「宣言の位置には気をつけろ」と書かれている。
primary.h の foo<T> の中でダミーでいいから sizoef(T) を使って、
不完全型ではインスタンス化できないようにしておけば、
いちおうエラーにすることができると思う。
348:デフォルトの名無しさん
05/02/28 11:44:49
template<class T> class A
{
public:
void hoge() { }
void foo() { }
// 他にいろいろなメンバがある
};
というクラステンプレートがあって、プログラム中でA<T>::hogeだけどこからも使われなかったとき
A<T>::hogeのコードは生成されるのでしょうか?
349:デフォルトの名無しさん
05/02/28 12:01:34
>>348
されない。だから定義しなくても大丈夫。
350:デフォルトの名無しさん
05/02/28 19:22:11
>>348
処理系依存
351:デフォルトの名無しさん
05/02/28 21:47:50
>>350
ほんと?
352:デフォルトの名無しさん
05/02/28 22:10:33
一応標準としてはAの暗黙のインスタンス化ではhogeはインスタンス化されません.(14.7.1/1)
ちなみにAの明示的インスタンス化の際にはhogeのインスタンス化が伴います.(14.7.2/7)
353:デフォルトの名無しさん
05/02/28 22:10:41
>350は狼少年
354:デフォルトの名無しさん
05/03/01 22:32:51
>>348
Modarn C++ Designの1.8に、生成されないことを前提にした技法があったな確か。
シンタックス・チェックだけは、実装によっては行われるんだったっけか。
355:デフォルトの名無しさん
05/03/02 01:29:19
Modern ね
356:デフォルトの名無しさん
05/03/02 12:31:04
スマソ
357:デフォルトの名無しさん
05/03/08 02:55:11
AdobeのASLもここでいいんかな?
358:デフォルトの名無しさん
05/03/08 10:23:35
使われているプログラミング技法を語るならここかな
あるいはBoostスレか
359:デフォルトの名無しさん
05/03/09 18:17:53
以下のコードで 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;
}
360:デフォルトの名無しさん
05/03/09 18:39:00
>>359
<set>の中からそのoperator<()が見えていない。しかしoperator<()を
#includeよりも前に持ってくると今度はcomplexが定義されていない。
しかしstd名前空間内部のものを先行宣言することは許されていない。
自分で関数オブジェクトを定義するしかない。
361:デフォルトの名無しさん
05/03/09 18:40:16
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));
}
}
で通ったけど、これってやっていいことだっけ……?
362:デフォルトの名無しさん
05/03/09 18:56:02
>>360
> <set>の中からそのoperator<()が見えていない。
これは関係ない。どうせグローバルのoperator<は使われない。
363:デフォルトの名無しさん
05/03/09 19:00:21
>>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.
364:デフォルトの名無しさん
05/03/09 19:17:37
>>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;
}
これ通らない?
365:デフォルトの名無しさん
05/03/09 21:08:49
>364
それはhogeとoperator<が同じ名前空間(グローバル)で定義されているので通りますよ.
std::complexを引数とする呼び出しからoperator<が見えるためには
operator<がstd名前空間で定義されていないといけないです.
でもそのような定義をstd名前空間に追加することは許されないので(>363),
自分で関数オブジェクトを書いて(>360)それをsetのテンプレート引数に与えるしかないです.
366:デフォルトの名無しさん
05/03/09 21:12:46
で、結局こう、と。
#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;
}
367:359
05/03/09 21:25:39
>>360-366
皆さんありがとうございます。よく分かりました。
ちゃんと勉強しないとダメだなぁ~ orz
368:デフォルトの名無しさん
05/03/09 21:55:23
string とか pair が std 名前空間に operator < を定義しているから
ADL のせいで operator < を std 名前空間の外に探しに行かないという認識であってますか?
369:デフォルトの名無しさん
05/03/09 22:09:23
↑俺には断言できん
↓あってるのか?
370:デフォルトの名無しさん
05/03/09 22:11:50
あってる。
371:369
05/03/09 23:24:46
>>368
あってるぞ。
よし、俺ツーポイントゲット。
372:デフォルトの名無しさん
05/03/10 04:08:30
その為に less がテンプレート引数になってるんではないのか。
…と、こないだ初めて map で less を使った俺が言いました。
373:デフォルトの名無しさん
05/03/11 02:09:30
練習で 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 ってないんですか?
あったら便利だと思うのですが・・・。
374:デフォルトの名無しさん
05/03/11 02:24:34
copy_ifはある。あとはback_inserterを組み合わせて使えばよし。
375:デフォルトの名無しさん
05/03/11 02:27:17
> copy_ifはある。
ウソだった。標準ではない。すまん。
376:デフォルトの名無しさん
05/03/11 02:36:13
>>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;
}
377:デフォルトの名無しさん
05/03/11 16:52:41
>>373
> for(;b!=e;b++)
++bにしたほうがいい。
378:デフォルトの名無しさん
05/03/11 19:43:05
>377
また荒れるようなことを
379:デフォルトの名無しさん
05/03/11 20:28:43
いやいや荒れるまでもなく当たり前の事ですよ
380:373
05/03/11 21:26:10
>>374-379
レスが遅くなってすいません。参考にします。
381:デフォルトの名無しさん
05/03/13 00:46:27
荒れてもいいから理由を教えろ
382:デフォルトの名無しさん
05/03/13 01:27:48
>>381
後置インクリメントだと、一時オブジェクトが必要になるから。
POD型の場合でもレジスタを余計に必要としたりね。
#それが理由で後置インクリメントを持たないクラスも作ることも多いし。
383:デフォルトの名無しさん
05/03/13 01:32:28
C++より++C
384:デフォルトの名無しさん
05/03/13 01:50:07
> POD型の場合でもレジスタを余計に必要としたりね。
は?
385:デフォルトの名無しさん
05/03/13 03:26:57
今 typeof が使えるコンパイラって g++, icc の他にどんなのがある?
typeofなんてぶっちゃけ template つかってないと殆ど使わんだろうしここでいいよね。
386:デフォルトの名無しさん
05/03/13 09:54:26
RTTIとテンプレートはあまり関係ないだろうと思いつつ、
ほとんどのメジャーなコンパイラは扱えますよ。
387:デフォルトの名無しさん
05/03/13 09:57:05
typeidじゃないよ。
388:デフォルトの名無しさん
05/03/13 12:31:23
メジャーじゃないコンパイラは"ほとんど"に含まれない言葉のトリック
389:デフォルトの名無しさん
05/03/13 13:47:16
そういうもんだいではない
390:デフォルトの名無しさん
05/03/13 17:59:47
#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;
}
391:デフォルトの名無しさん
05/03/13 18:00:22
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;
};
392:デフォルトの名無しさん
05/03/13 18:15:58
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; }
};
393:デフォルトの名無しさん
05/03/13 18:17:47
typeof って何で標準に入る予定ないの?
394:デフォルトの名無しさん
05/03/13 18:21:14
最初からplus_resultのとこにtypeofを書けばいいような?
395:デフォルトの名無しさん
05/03/13 20:16:10
>>393
そんなこと誰が言ったんだ?
396:デフォルトの名無しさん
05/03/13 22:50:55
条件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);
}
}
397:デフォルトの名無しさん
05/03/13 23:18:26
>>396
じゃ遠慮なく。
・名前の省略するな。(×IIte → ○InputIterator)
・Pred は predicate(述語) の略なので、 bool を返す関数以外には使うな。(×ApplyPred → ○UnaryFunction)
・*begin が繰り返されているのは良くない。
・std::for_each() に倣って UnaryFunction を戻り値としたほうがいいかもしれない。
398:デフォルトの名無しさん
05/03/14 00:29:28
>>397
細かいことを言えば、
InputIterator に apply はまずい。
InputOutputIterator じゃ長いけど。
399:デフォルトの名無しさん
05/03/14 01:03:01
とりあえず試しに Visual C++ Toolkit 2003 を使ってみたけど、
typeof() は使えない模様。__typeof とかなんかあったりするのかな?
400:デフォルトの名無しさん
05/03/14 01:06:34
>>398
イテレータのコンセプトを表すという意味で InputOutputIterator はありえない。
出力も兼ねると言うことなら、現行の規格では ForwardIterator が候補になるだろう。
しかしここも std::for_each() に倣って InputIterator とするのが正解だろう。
401:デフォルトの名無しさん
05/03/14 01:13:19
なんなんだよ、typeof()って?
初めて聞いたぞ。
type_infoクラスとtypeid演算子ならC++にあるけど、
typeof()は何をするためのもの?
402:デフォルトの名無しさん
05/03/14 01:21:18
>>401
まず最初に言っておくと、typeofは今のところまだ標準には無い。
で、まぁ名前の如く変数の型を得る演算子(?)の事。
Type a;
typeof(a) b = a;
みたいに使える。
この例では a の型が分かってるけど、Expression Template なんかの場合はどえらい事になっちゃうっしょ。
って分かりにくいかなぁ。誰か分かりやすい例キボンヌ。
403:デフォルトの名無しさん
05/03/14 01:27:44
その程度だとtypeid, type_infoとどう使い方が違うのか見えんな。
404:デフォルトの名無しさん
05/03/14 01:29:18
テンプレート宣言の
template<typename HOGE>
を適宜、
template<typename HOGE, typename PLUS_TYPE>
にすれば回避できるんじゃないの?
曖昧さの解決にもなるし。
というか、C++とtypeof()は相性が最悪な気がする。
多重継承さえ嫌がる人が多いというのに、
typeof()は、無駄にデバッグ作業を増やさせるだけではないか?
405:デフォルトの名無しさん
05/03/14 01:31:35
>>400
ForwardIteratorが正しいね。
しかし、InputIterator で要素の変更を行うのは論外では?
for_each()は変更を伴わない関数。
本質的に違う関数に倣うという理由付けも理解に苦しむ。
406:デフォルトの名無しさん
05/03/14 02:01:52
>>405
std::for_each() で要素の変更は許される方向にあるらしい。
URLリンク(www.open-std.org)
「いまさら禁止されては困る」という本音が多分にあるだろうと思うので、
明示的に許可を後付けされてもすっきりしないよな。
はっきりと Mutating algorithm に移動させて欲しい。
407:デフォルトの名無しさん
05/03/14 08:46:06
>>403
オマエの目は節穴なのでしょうか?
408:402
05/03/14 11:23:16
>>403
うーん、例が悪いでしょうかねぇ。ただ、typeidと決定的に違うのが、
「コンパイルタイムに決まる」、という事。
んだから、「謎の型を宣言、定義可能」って事なんですけどね。
明日から海外飛ぶんで誰かフォローよろ。
409:デフォルトの名無しさん
05/03/14 12:32:23
俺も来週から地方飛ばされるんで
誰か助けてくれ
410:デフォルトの名無しさん
05/03/14 12:37:00
俺はneetなんである意味助けてくれ
411:デフォルトの名無しさん
05/03/14 12:37:50
>>408,409
そのままキャッチされない例外に飛ばされて人生の強制終了。
412:デフォルトの名無しさん
05/03/14 12:43:12
C++よりMLの方がいいよ。
413:デフォルトの名無しさん
05/03/14 12:45:00
メーリングリスト
414:396
05/03/14 23:32:14
>>397,398,400,401,405,406
参考にしたいと思います。ありがとうございます。
415:デフォルトの名無しさん
05/03/15 00:04:29
C++よりMLの方がいいよ。
416:デフォルトの名無しさん
05/03/15 00:16:03
>>412
>>415
利点をあげてくれ、なにがいいのかわからん
417:デフォルトの名無しさん
05/03/15 00:47:28
このスレが不要になるぐらい明快
418:デフォルトの名無しさん
05/03/16 07:47:07
そうか、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なしでも同じようなことができるかも。
419:デフォルトの名無しさん
05/03/16 08:08:57
>>418
boost spirit typeof
420:418
05/03/16 09:26:00
どうもboostの定義をみてるとMetrowerksにもtypeofがあるようだ。
んで、typeofのテンプレートによる実装もあるみたいだね。
URLリンク(aspn.activestate.com)
boostのsandboxにtypeofの実装があるらしい
URLリンク(aspn.activestate.com)
Code Projectの記事。typeofのVC7用実装。
これによるとboost::mplにも
BOOST_MPL_AUX_REGISTER_TYPE(123, abc);
abc aa1;
BOOST_MPL_AUX_TYPEOF(_, aa1) *aa2 = &aa1;
というtypeofがあるらしいがundocumentedだのuglyだの不便だのと切って捨てている。
>>419
? よくわからんちん。
421:デフォルトの名無しさん
05/03/16 15:39:09
>>420
URLリンク(boost.cppll.jp)
typeofはレビュー待ちの状態だと以前読んだ希ガス
422:デフォルトの名無しさん
05/03/16 16:23:33
>>420
Metrowerks CodeWarriorでの話。
__typeof__()演算子があって、これは常に使える。typeof()演算子を使うには
#pragma gcc_extensions onとする必要がある。こうすると、以下のGNU Cの言語
拡張機能を利用します。
・auto変数の構造体、または配列を、定数以外の値で初期化することを許可します。
・sizeof( void ) == 1
・sizeof( function-type ) == 1
・評価式の内部のGCCステートメントと宣言を、制限付きでサポートします。
・#undefがその前にないマクロの再定義。
・GCCのtypeofキーワード。
423:デフォルトの名無しさん
05/03/17 09:40:37
>418
>boostのlambdaみたいにすればtypeofなしでも同じようなことができるかも。
逆だと思いますよ.lambdaも状況は似たようなもので
むしろlambdaもtypeofがあればいろいろうれしいです.
でもboostのtypeofの実装はさすがにやりすぎな気が・・・
そもそもtypeofの機能をライブラリで提供する/できるというのが異常というか
424:418
05/03/17 10:10:08
420のCode Projectの方のリンクが寝惚けてました^^; 正しいのはこっち。
URLリンク(www.codeproject.com)
>>421
すいません、あいかわらずよくわかりません。subruleが普通のコードでも使え
るってこと? 数字を手で入れる必要があるのは面倒なような……。
>>422
補足サンクスです。そうそう、__typeof__でした。
そうか、MetrowerksはGCC拡張を一部サポートするんですね。
425:デフォルトの名無しさん
05/03/25 00:52:31
gcc 3.4のバグだろうか。
テンプレート関数の中で
boost::mpl::identity<typeof(foo->get_bar())>::type bar;
と変数を定義しようとすると何故か
expected `;' before "bar"
というエラーになる。
普通の関数の中なら問題なく通るのだけど。
426:デフォルトの名無しさん
05/03/25 00:58:26
>>425 typname
427:デフォルトの名無しさん
05/03/25 02:26:51
>>426
サンクス。
typenameは試したはずなんだけど……と思いつつやってみると
コンパイル通りました。吊ってきます。
428:デフォルトの名無しさん
05/03/30 01:09:51
Boost.Serialization の
#include <boost/serialization/shared_ptr.hpp>
にある
#define private public
#include <boost/shared_ptr.hpp>
#undef private
って、shared_ptr の方を変更してもらえないんですかね?
別のスレッドで Boost.Serialization を教えてもらったんですけど、
これが、ちょっと気になります……。
429:デフォルトの名無しさん
05/03/30 01:17:26
変更して貰えるわけないだろ、氏ね(ここまで一筆書き)
430:428
05/03/30 02:21:20
>>429
Boost 同士ということで friend にしてもらうくらいなら、
と思ったんですが、直接には関係しない物のために変更するのは、
やっぱり無理ですよね。
431:デフォルトの名無しさん
05/03/30 04:00:47
そういうのはここで訊くよりboostのメーリングリストを検索した方がいいのでは。
432:428
05/03/30 05:05:42
>>431
読んでも分からなさそうと言う事で避けてました。すみません。
で、検索してみたら、そのままの議論がありました。
が、やっぱり分かりませんでした。orz
ただ使うだけにします。ありがとうございました。
433:デフォルトの名無しさん
05/03/30 05:40:36
そういう場合はスレッドのURLとか貼っておくといいかもね。
434:デフォルトの名無しさん
05/03/30 13:22:32
Serializetionがオブジェクトを覗き見しなきゃいけないことを>>428は理解してないのか?
shared_ptrの方で変えたら、通常利用で保護出来ないじゃないか。
435:デフォルトの名無しさん
05/03/30 13:57:46
>>434
>>430
436:ヽ(´ー`)ノ ◆.ogCuANUcE
05/03/30 18:14:32
これかな?
URLリンク(lists.boost.org)
437:428
05/03/31 11:07:00
>>436
それです。
shared_ptr の人も交えて、実装に立ち入った問題点などが議論されていて、
日頃使っているだけの私では、良く分かりませんでした。
438:ヽ(´ー`)ノ ◆.ogCuANUcE
int 2ch =05/04/01(金) 20:35:21
>>437
つか、Thread Index で変なとこに飛ばされて、
議論が追っかけずらいんだよね(´・ω・`)
439:デフォルトの名無しさん
int 2ch =05/04/01(金) 23:10:42
>>438
URLリンク(thread.gmane.org)
440:デフォルトの名無しさん
05/04/10 19:16:42
Spiritのアクションってなんで2引数必要なの?
値を代入したい時は冗長になるぅ...
expr = (str_p(L"1"))[boost::lambda::_1,boost::lambda::_2,data=1];
441:デフォルトの名無しさん
05/04/12 10:09:35
template<class T> class A
{
public:
A(const A&); // 引数
A func() // 返り値
{
A a; // 自動変数
return a;
}
};
クラステンプレートで上記のコメントのところのように
Aとだけ書いた場合A<T>と同じ意味になる、という解釈は正しいですか?
442:デフォルトの名無しさん
05/04/12 10:39:06
>>441
正しいです。
URLリンク(www.kuzbass.ru)
443:441
05/04/12 11:09:04
>>442
ありがとう。よくわかりました。
444:デフォルトの名無しさん
05/04/22 04:23:40
鬼車みたいに
マルチバイトで正規表現使えると速度面では有利なのかな?
ワイド文字で
System.Text.RegularExpressions(C#)
boost::wregex
boost::expressive
boost::spirit
試してみたけど敵わなかった...
鬼車>>C#>=boost::wregex>>expressive>>>>>>spirit
445:444
05/04/22 04:52:13
>>444
spiritのパーサの型がわからんかったんで
毎回生成してたは...道理で遅いはずや...
typeid(parser).name()で出力された型にparser保存してループ回したら
鬼車=spiritになったわ...
逝ってくる...
446:デフォルトの名無しさん
05/04/22 21:22:11
CommonLispの正規表現が最速
447:デフォルトの名無しさん
05/04/22 23:32:46
>>445
当たり前だ。C++が遅かったら、コンパイラ言語を使って正規表現を扱う意味が
ないやんけ。
448:デフォルトの名無しさん
05/04/23 01:11:14
コンパイラ言語?
式テンプレートを使ったメタプログラミングのこと?
449:デフォルトの名無しさん
05/04/23 09:45:54
インタプリタ言語と比較してるだけっしょ
450:デフォルトの名無しさん
05/04/23 10:03:21
またなんかミクロな揚げ足取りしてるんだろうね、きっとw
451:デフォルトの名無しさん
05/04/23 10:19:30
>>448
友達いないでしょ。
452:デフォルトの名無しさん
05/04/23 10:23:08
>>448
どういう風に表現すれば一番適切なのか教えて。
>>450-451
おまえらはどうでも良い。
453:デフォルトの名無しさん
05/04/23 10:31:09
言い負けるのが余程悔しいんだろうな。
リアルな世界では気の強さが災いして、友達どころか彼女もいないと思われる。
家族にも総スカン。
454:デフォルトの名無しさん
05/04/23 10:32:56
>>453
どうしてそういう返事をつけるのかな?
普段よっぽど抑圧されてるのか? もっと自分を愛そうね。
455:デフォルトの名無しさん
05/04/23 10:36:57
スレタイ嫁
456:デフォルトの名無しさん
05/04/23 10:51:39
>>447は、C++のコードをコンパイルして実行から速いと言っているのか、
汎用のDFSマシンじゃなくて、式テンプレートを使ったメタプログラミングで、
専用レクサーを生成して実行しているから速いと言っているのか、
どっちなんだ? 両方か?
457:デフォルトの名無しさん
05/04/23 17:26:58
>>456
真性のアフォ?
458:デフォルトの名無しさん
05/04/24 04:51:27
GCC 4.0.0 に TR1 が来ましたね。うれしい。
ソースは boost のごちゃごちゃしたコンパイラ分岐が無くなった分、
だいぶすっきりした印象
459:445
05/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
05/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
05/04/24 10:49:54
int main()
{
int a=100;
make_typeof(a,1212);//初回に必要
typeof(a) aa=100;//make_typeof実行後に有効
}
462:デフォルトの名無しさん
05/04/25 22:32:41
これってtypeofを使う前にmake_typeofを書いた実行ファイルを走らせないといけないですよね?
実用上かなり使いにくくないですか?
463:445
05/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
464:デフォルトの名無しさん
05/04/26 00:53:50
BOOST_TYPEOF_REGISTER_TEMPLATEは飾りなんです
偉い人にはそれがわからんのです
465:Lispのマクロテンプレート
05/04/26 01:04:31
俺の話を聴け~♪
五分だけでいい~♪
466:デフォルトの名無しさん
05/05/07 00:44:34
俺しかいない羊羹マン
467:デフォルトの名無しさん
05/05/07 00:47:41
ノシ
468:デフォルトの名無しさん
05/05/08 12:54:43
質問です。
以下の要件を満たす型に対する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 { // ここは?
// ?????....
};
よろしくお願いします。
469:デフォルトの名無しさん
05/05/08 13:28:55
>>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
05/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
05/05/08 14:56:37
すみません、訂正です。
: public Base<ContainerTemplate<std::pair<int, PairSecond> > >
: public Base<ContainerTemplate<int, PairSecond> >
でした。
472:デフォルトの名無しさん
05/05/08 22:00:30
std::vector<int, MyAlloc>なんかが、特殊化される悪寒w
473:デフォルトの名無しさん
05/05/09 11:32:52
std名前空間のものを
std名前空間のもので特殊化ないし部分特殊化するのは
可能だがやっちゃダメ
474:デフォルトの名無しさん
05/05/09 12:36:59
>>472
MyAlloc どころか普通の std::vector<int> も特殊化される罠
>>473
この場合、特殊化してるのは vector/deque/map じゃなくて
A のほうだから問題ないんじゃないかと思うんだが
475:468
05/05/09 13:06:57
Baseで typedef typename T::value_type::first_type first_type
とか、諸々のstatic_assert置いておけばなんとかなると踏んでたんですが、
やっぱ変でしたかねぇ。
476:468
05/05/09 13:22:32
たびたびすみません、これだとA<std::vector<int> >が作れないや。
勉強して出直します。
477:473
05/05/09 16:30:48
>>474
あ、>>468のvector,deque等の例に対して言ったんです。
478:468
05/05/09 17:44:25
>>473
468では、Aに渡す型の例としてvector,dequeをあげたのであって、
vector,dequeの特別バージョンを作ることを意図したわけではないのです。
479:デフォルトの名無しさん
05/05/09 18:19:20
>468
ユーザ定義型が絡む場合ならば,std::vector等のstd名前空間内のテンプレートを
特殊化することは許されているんですけれどね.
そもそも468は恐らくソート済みシーケンスとstd::mapを汎用に扱おうとする意図だと
思いますけれど,これらは各種メンバ関数の宣言その他もろもろからして違うので
汎用に扱おうとするのはかなり無理がないですか?
480:468
05/05/09 18:44:11
何度もすみません。
>そもそも468は恐らくソート済みシーケンスとstd::mapを汎用に扱おうとする意図だと
>思いますけれど,
その通りです。
>これらは各種メンバ関数の宣言その他もろもろからして違うので
>汎用に扱おうとするのはかなり無理がないですか?
無理がありました(汗 いろんなことが出来ませんでした。
とりあえず設計が悪かったということみたいです。
481:デフォルトの名無しさん
05/05/09 18:52:39
>480
それがやりたいならstd::vectorやstd::dequeをラップして
std::mapの要求に合うようにするアダプタ作るのが恐らく最良じゃないかと思います.
それを状況に応じてstd::mapととっかえひっかえする感じで.
482:デフォルトの名無しさん
05/05/10 00:38:29
boostにそんな感じのクラスなかったっけ?
似たようなニーズがあってboostを眺めたらあったので後で余裕があったら使おうと
思いつつ、遅いけどその場はstd::listで済ませたという覚えがある。
そういやその後試してなくてそのままになってるな。
483:デフォルトの名無しさん
05/05/10 00:43:11
multi_index_container
484:デフォルトの名無しさん
05/05/10 00:59:28
>>482
キーと値のアクセスの汎用化、ということなら property_map なんかもそうかな。
あとは boost-sandbox に associative_vector,vector_set なんてのもあるみたいだね。
485:デフォルトの名無しさん
05/05/10 01:05:27
>>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);
};
486:デフォルトの名無しさん
05/05/10 01:06:01
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> { ... }; // 特殊化版
487:デフォルトの名無しさん
05/05/10 02:23:21
>485
細かいことですけどmapのkey_typeってconstですよ.
SFINAEのこういう使い方はあくまで
「必要条件を満たさないものを振り落とす」ってだけなんですよね.
それにできることが基本的な型特性と内部型の存在のテストくらいだし・・・.
せめてメンバ関数の存在をテストできればもう少し面白いと思うんですけれど.
488:デフォルトの名無しさん
05/05/10 03:24:21
>>487
いや、value_type が pair<const Key, T> なのであって、
key_type は Key のままだよ。
そうでないと一時変数作れないし。
489:デフォルトの名無しさん
05/05/10 09:27:04
>>487
> せめてメンバ関数の存在をテストできればもう少し面白いと思うんですけれど.
typeof(メンバ関数)で何とかなります。
490:デフォルトの名無しさん
05/05/10 10:28:50
>488
マジボケしてました・・・.
>489
何とかなります?typeofってそもそも非標準ですし.
491:ヽ(´ー`)ノ ◆.ogCuANUcE
05/05/10 10:36:09
>>490
まだ sandbox だけど boost::typeof とか。
boost スレかどっかで見たけど、どこだったか忘れた。
492:デフォルトの名無しさん
05/05/10 14:30:49
>>489
これとか見ると、メンバ関数のシグネチャが分かれば
なんとかできそうな気はする
URLリンク(lists.boost.org)
493:デフォルトの名無しさん
05/05/10 22:34:40
>>491
typeofがあってもメンバがなければ単にコンパイルが失敗するだけじゃないですか?
>>492
汎用プログラミングの文脈だと「~~というシグネチャを持ったメンバ関数があるかどうか」というテストより
「~~という構文でメンバ関数が呼び出せるかどうか」というテストの方が重要だと思うので,
そこで使われている技法は少なくとも汎用プログラミングでは非常に使いづらいような気がします.
それにその技法,言語規格的に結構スレスレなことやってるので,GCCではうまく通らなかったり
VC7.1でもうまく機能しないケースがあったり・・・.
494:デフォルトの名無しさん
05/05/11 00:30:14
>>493
> typeofがあってもメンバがなければ単にコンパイルが失敗するだけじゃないですか?
traitsみたいなんじゃ不十分で、条件分岐とかしたいという事?
495:ヽ(´ー`)ノ ◆.ogCuANUcE
05/05/11 10:34:33
>>493
失敗するだけだね。boost::mpl::has_xxx とかで何とかできないかとも思ったが、
寝不足なせいか、頭がこんがらがってきた。
496:デフォルトの名無しさん
05/05/11 19:59:54
>>494
そうです.traitsというよりはintrospectionといったほうが適切ですかね.
traitsはユーザが明示的に特殊化する分,確実ですけれど一方で面倒な側面もあると思うので,
ある程度は要件を自動的にテストしてくれたほうが楽かなという発想です.
>>495
boost::mpl::has_xxxは内部型の存在テストにしか使えないです.
497:デフォルトの名無しさん
05/05/12 00:23:09
>>496
> そうです.traitsというよりはintrospectionといったほうが適切ですかね.
traitsとも違い、
virtual classをinheritしたり、
interfaceをimplementsするのとは違う用途は、
具体的にどういうものを想定しているんですか?
498:デフォルトの名無しさん
05/05/12 03:28:39
>>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の明示的な特殊化に頼ることなく
上記のような高度な振り分けができるんじゃないか,という考えです.
ただ,もちろんメンバ関数の存在テストはコンセプトの必要条件を調べられるだけで,
決してコンセプトのモデルであるための十分条件を調べることにはならないのですが・・・.
499:デフォルトの名無しさん
05/05/12 03:29:37
・・・ということを想定していたんですが,
URLリンク(tinyurl.com)
上のような議論を見つけたので読んでみた結果,やはりtraitsの特殊化などで
明示的に表明する方が良いような気がしてきました.より根本的には
言語としてこういうことを直接サポートしてくれればもっとうれしいのですけれど.
URLリンク(www.open-std.org)
500:デフォルトの名無しさん
05/05/12 12:05:02
上記PDFもそうだけど、D&Eの書き下ろし前文(-1章)を見ても、
コンセプト回りの拡張が c++0x でなされる可能性は高いんじゃないかな。
ただ、Stroustrup としても
テンプレート回りのエラーメッセージの酷さを何とかすることや、
テンプレート宣言と定義の分離問題を何とかするために導入したいような
感じだし、基本的にはコンパイル時検査の強化を目的としたものであって、
オーバーロード選択などに使われるようなものではないと思う。
例えば、関数ポインタのシーケンスがあったとして、
operator== による find なのか、operator() による find_if なのか、
コンセプトだけでは判断できないケースもあるわけで。
501:デフォルトの名無しさん
05/05/12 19:39:36
>>500
> 使われるようなものではないと思う。
けど,使われるようなものではないものに,使われて驚くのがtemplateだしなあ…
502:デフォルトの名無しさん
05/05/13 01:07:52
>>500
>テンプレート回りのエラーメッセージの酷さを何とかすることや、
>テンプレート宣言と定義の分離問題を何とかするために導入したいような
これは前々からずっと言ってますからねぇ.近い将来標準に導入されると信じていますけれど.
>例えば、関数ポインタのシーケンスがあったとして、
>operator== による find なのか、operator() による find_if なのか、
>コンセプトだけでは判断できないケースもあるわけで。
う,やはりここ突っ込まれますよね・・・.こういう曖昧なケースではユーザが
明示的に曖昧性を解消するような方向を想定してました.微妙ですけれど.
やはり現在の段階では,コンセプトに基づくオーバーロード選択や
テンプレートの特殊化といった発想は飛躍しすぎている感がありますね.
503:デフォルトの名無しさん
05/05/14 03:29:59
参照templateのパラメータに制限あるのかな?
グローバル変数しか使えないみたいなんだが...
struct A{};
template <A& a>struct C{};
A a;//OK
int main()
{
A a;//NG
C<a> c;
}
504:デフォルトの名無しさん
05/05/14 05:10:48
>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 の補足。
505:デフォルトの名無しさん
05/05/14 09:10:05
テンプレートはコンパイル時に生成されるわけで
mainの方のaは実行してみないとどこに作られるかわからないわけで
そのaをテンプレート引数にstruct Cは生成できないわな。
506:デフォルトの名無しさん
05/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: 構文エラー : ';' が '<' の前にありません。
507:デフォルトの名無しさん
05/05/15 21:28:04
>>506
URLリンク(www.kuzbass.ru)
ここに明示的な特殊化の対象となるものがリストされているんだが、
"member function template of a class template" はあるけど、
"member function template of a class" は無いな。
できないのかもしれない。
508:デフォルトの名無しさん
05/05/15 21:51:51
>>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:デフォルトの名無しさん
05/05/15 21:56:00
>>506
理解しました。ありがとうございました。
しかし皆さん凄いですね。
510:デフォルトの名無しさん
05/05/15 21:56:33
>>506
というわけで
「コンストラクタテンプレートぐらいhppに全部書いちゃえば良いじゃない」
もしくは
「コンストラクタテンプレート内の処理を静的メンバ関数に委譲して
(この部分だけはhppに書く必要アリ)
委譲先の静的メンバ関数を明示的にインスタンス化すれば良いじゃない」
511:デフォルトの名無しさん
05/05/15 22:32:53
ん?これでできてるっぽいぞ。
template<> A::A( int b);
512:デフォルトの名無しさん
05/05/15 23:29:21
>>511
あれ?本当だね。という事は、template <>の構文がちゃんとメンバテンプレート
に適用されているみたいだね。俺の勘では、明示的特殊化になってなくて、単なる
オーバーロードのような気もするが・・・・
513:デフォルトの名無しさん
05/05/15 23:36:57
もう少し規格票をよく読んでみる・・・・・
>>508はそしたら違う事に関してなのかな。
514:デフォルトの名無しさん
05/05/15 23:41:09
>>511
しかし、そのコードは構文的に正しいとは言えないですよね。
謎だ。
515:デフォルトの名無しさん
05/05/15 23:41:17
特殊化とインスタンス化とを混同してない?
516:デフォルトの名無しさん
05/05/15 23:55:33
>508が示したように、コンストラクタテンプレートに対して
テンプレート引数を明示する方法は無い。
しかし、(メンバ)関数テンプレートの特殊化を宣言する再には、
テンプレート引数を明示しなくても、関数引数の型から
テンプレート引数の推測が働く。
>>514
明示的特殊化の構文は
template<> delcaration
だから、>511は構文的に正しいと言える。
517:デフォルトの名無しさん
05/05/15 23:58:48
構文的には確かに正しいのだけれど、もともとの506の要求は
明示的インスタンス化(≠明示的特殊化)なわけで・・・
518:デフォルトの名無しさん
05/05/16 00:02:05
勉強になった。
519:デフォルトの名無しさん
05/05/16 00:08:01
>>517
それがどうした?
明示的インスタンス化の構文は
template declaration
だ。あとは同じ。
520:デフォルトの名無しさん
05/05/16 00:12:53
>>519
すまんすまん。それでVC++7.1で通ったよ。
521:デフォルトの名無しさん
05/05/16 00:15:29
コンパイラに「これこれのテンプレートをT型でインスタンス化しますた」
とレポートするスイッチがあればいいのに
522:デフォルトの名無しさん
05/05/16 00:17:31
実体化の位置を決定するルールは結構複雑だからな。
523:デフォルトの名無しさん
05/05/16 00:59:29
おまえらの必死さに笑った。
C++の中途半端なtemplate機能でメンテ不能の駄作を量産してる様は、
まるでVBで汎用ライブラリを作る馬鹿とそっくりだな。
524:デフォルトの名無しさん
05/05/16 01:03:16
C++知らないのに、知ってる振りして
がんばって煽るアンタもそうとう必死だが
525:デフォルトの名無しさん
05/05/16 01:35:46
むしろC++で駄目なのは
テンプレートじゃなくてコンストラクタ
526:デフォルトの名無しさん
05/05/16 01:47:19
>>525
コンストラクタの何が不満だって?
527:デフォルトの名無しさん
05/05/16 02:48:50
純粋なOO言語と比べると
C++のOOは不完全
528:デフォルトの名無しさん
05/05/16 03:05:21
>>526
class A
{
int a;
public:
A( int a_ ) : a(a_){;}
};
class B : A
{
public:
B(){ int a = 略; A::A(a);}
B( int a ) : B(){;}
};
529:デフォルトの名無しさん
05/05/16 03:16:11
何がしたいのか理解に苦しむ。C++について理解しているとは思えないコードだ。
530:デフォルトの名無しさん
05/05/16 03:30:52
>>529
これが出来ないから嫌だなと。
>B(){ int a = 略; A::A(a);}
これはAに突っ込む引数aを
Bのコンストラクタ内で生成したい時。
C++ではAのコンストラクタは、Bの初期化リストにしか
置けないので複雑なロジックは難しい。
>B( int a ) : B(){;}
これは多重定義したコンストラクタから
デフォのコンストラクタを予呼びたい時。
デフォのコンストラクタに生成時にかならず呼ばれる
初期化コードを収める。
これが出来ないと全てのコンストラクタに
同じ初期化コードを書かなければならない。
531:デフォルトの名無しさん
05/05/16 04:43:03
>>530
最初の:AはBの基底クラス。最初にAが構築されなきゃBが構築できない。
2番目の:B() {Init();} B(int a) {Init();hogehoge(a);}
532:デフォルトの名無しさん
05/05/16 08:55:21
最初のは
static int hoge() {return 略}
B() : A(hoge()) {}
とかすれば。
533:デフォルトの名無しさん
05/05/16 09:05:50
>>530
そういうことか。
ではどうしたらいいと思う?
Dは両方いけるんだっけか?
534:デフォルトの名無しさん
05/05/16 09:06:24
>>531
> Aが構築されなきゃBが構築できない
関係ない。
> Init()
Init() の中に初期化リストが書けない。
535:デフォルトの名無しさん
05/05/16 09:07:23
>>532
hoge() の値を初期化リストで2度使いたくなったらやっぱり困るな。
「略」が軽くて副作用がなければ、2回呼び出すんだろうけど。
536:デフォルトの名無しさん
05/05/16 09:10:37
要は設計が悪いんだろ。
537:デフォルトの名無しさん
05/05/16 09:18:31
まあそうだな。C++の設計の悪さは今更いかんともしがたい部分がある。
538:デフォルトの名無しさん
05/05/16 11:19:33
>>530
> C++ではAのコンストラクタは、Bの初期化リストにしか
> 置けないので複雑なロジックは難しい。
コンストラクタの途中でexceptionが起きたことを考えると、
>>532のような方法で初期化リストを旨く使う方法に頭を悩ませるのが良い。
>>528のやり方ではコンストラクト失敗時のデストラクトの扱いがかなり難しくなる。
初期化リストで上手くできない場合は、
exception safeの事を考えるとコンストラクタ自体がかなり複雑になってしまう。
539:>>538
05/05/16 11:21:07
定義順じゃなくて、初期化リスト記述順だといいのになあと思ったことはある。
540:デフォルトの名無しさん
05/05/16 12:06:24
>>539
それだと、コンストラクタごとに初期化順が変わってしまう。
Ex.
class foo {
public:
foo() : a_(), b_() {}
foo(int a) : b_(a), a_(a) {}
...;
};
541:デフォルトの名無しさん
05/05/16 12:21:40
>>540
539はまさにそれを意図しているのだと思うが、何か不都合があるの?
542:デフォルトの名無しさん
05/05/16 12:53:52
>>541
初期化リストに載ってないメンバはどうすればいい? by コンパイラ
543:デフォルトの名無しさん
05/05/16 13:14:10
くるしゅうない。よきにはからえ。
544:デフォルトの名無しさん
05/05/16 13:17:59
構築した順番の逆順で解体することを保証しなきゃならんので
コンストラクタごとに初期化順が変わったら大変だ。
545:デフォルトの名無しさん
05/05/16 14:05:33
なるほど。それもそうだ。
546:デフォルトの名無しさん
05/05/16 15:32:47
つーか藻前らEffectiveC++くらい読んどけよ。
547:デフォルトの名無しさん
05/05/16 20:25:46
template< uint n > class X
{
public:
void f(...);
}
こういうクラスがあったとして、
nが1だった場合 → X::f( uint f0 );
nが2だった場合 → X::f( uint f0, uint f1 );
nが3だった場合 → X::f( uint f0, uint f1, uint f2 );
こういうふうにテンプレート引数によって
関数の引数の数が変わるようにしたいんですが可能ですか?
出来ないまでも、代替手段みたいなのはありますか?
548:デフォルトの名無しさん
05/05/16 20:53:37
あの~
templateって実はマクロ?
549:デフォルトの名無しさん
05/05/16 21:23:34
>>547
関数のデフォルト引数でなんとかしろ。同一のテンプレートパラメータの型を
持つクラスは2回以上は定義できん。
550:デフォルトの名無しさん
05/05/16 21:58:37
>>549
了解、こういうのも出来るといいですね。
551:デフォルトの名無しさん
05/05/16 22:15:27
いやだから、ディフォルト引き数で何が不満なんだ?
552:デフォルトの名無しさん
05/05/16 22:22:47
それぞれ特殊化で可能じゃない?もちろんそうするのが良いか悪いかは別。
553:デフォルトの名無しさん
05/05/16 22:26:17
>>551
例えばベクトルクラスがあります。
template< uint n >class vector;
これをインスタンス化したい場合、こういうふうに書きたいんです。
vector<2> v2 = vector<2>(5,1);
vector<3> v3 = vector<3>(5,1,6);
vector<4> v4 = vector<4>(5,1,6,3);
vector<5> v5 = vector<5>(5,1,6,3,9);
vector<100> v100 = vector<100>(5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9, 5,1,6,3,9,5,1,6,3,9);
自然な欲求だと思います。
554:デフォルトの名無しさん
05/05/16 22:31:08
>>553
そういう時のためのstd::vectorではないかと思うのだが・・・・
555:デフォルトの名無しさん
05/05/16 22:34:16
static const uint initialValues[] = {5, 1, 6, 3, 9,};
std::vector<uint> v5 = std::vector<uint>(initailValues, initialValues + sizeof(initialValues) / sizeof(*initialValues));
556:デフォルトの名無しさん
05/05/16 22:34:58
その例なら
配列を初期化して、std::vectorにぶち込めばいいじゃん
どうしてもやりたいならBOOST_PPで特殊化
557:デフォルトの名無しさん
05/05/16 23:09:19
部分特殊化。以降略。なんか馬鹿みてえ。
#include <iostream>
#include <cstddef>
template <std::size_t N, typename T = int>
class vec {
T a[N];
public:
vec(T i) {
a[0] = i;
std::cout << a[0] << std::endl;
}
};
template <typename T>
class vec<2, T>
{
T a[2];
public:
vec(T i, T j) {
a[0] = i; a[1] = j;
std::cout << a[0] << ' ' << a[1] << std::endl;
}
};
int main()
{
vec<1> v1 = vec<1>(5);
vec<2> v2 = vec<2>(5,1);
}
558:デフォルトの名無しさん
05/05/16 23:21:18
特殊化はイヤというか面倒くさすぎるから、普通はこんなカンジだろうね
template<uint Dim> class vector {
double *const coord;
public:
vector(double x) : coord(new double[sizeof(char[Dim == 1]) * Dim])
{ coord[0] = x; }
vector(double x, double y) : coord(new double[sizeof(char[Dim == 2]) * Dim])
{ coord[0] = x; coord[1] = y; }
vector(double x, double y, double z) : coord(new double[sizeof(char[Dim == 3]) * Dim])
{ coord[0] = x; coord[1] = y; coord[2] = z; }
};
int main() {
vector<1> v(1);
vector<1> v1(1, 2); // error
vector<2> v2(1, 2);
vector<2> vv2(1); // error
vector<3> v3(1, 2, 3);
}
559:デフォルトの名無しさん
05/05/16 23:24:56
やはりコンストラクタのオーバーロードに落ち着くか。
560:デフォルトの名無しさん
05/05/16 23:25:18
>>
そうするまでもなく
普通に多重定義でいいと思うよ。
template <std::size_t N, typename T = int>
class vec {
T a[N];
public:
vec( T x, T y)
{
if( N > 0 )a[0] = x;
if( N > 1 )a[1] = y;
}
vec( T x, T y, T z)
{
if( N > 0 )a[0] = x;
if( N > 1 )a[1] = y;
if( N > 2 )a[2] = z;
}
};
561:デフォルトの名無しさん
05/05/16 23:27:04
ちなみに、 sizeof(char[Dim == 1]) ってのは、
Dim == 1 のときは、1 で、そうでなければ、コンパイルエラーね
562:デフォルトの名無しさん
05/05/16 23:59:25
どうも読みにくいので、直した
template<unsigned Dim> class vector {
double coord[Dim];
public:
vector(double x) {
sizeof(char[Dim == 1]); // Dim == 1 でなければエラー
coord[0] = x;
}
vector(double x, double y) {
sizeof(char[Dim == 2]); // Dim == 3 でなければエラー
coord[0] = x; coord[1] = y;
}
vector(double x, double y, double z) {
sizeof(char[Dim == 3]); // Dim == 3 でなければエラー
coord[0] = x; coord[1] = y; coord[2] = z;
}
};
int main() {
vector<1> v(1);
vector<1> v1(1, 2); // コンパイルエラー
vector<2> v2(1, 2);
vector<2> vv2(1); // コンパイルエラー
vector<3> v3(1, 2, 3);
}
563:デフォルトの名無しさん
05/05/17 02:55:12
おまえらの必死さに笑った。
C++の中途半端なtemplate機能でメンテ不能の駄作を量産してる様は、
まるでVBで汎用ライブラリを作る馬鹿とそっくりだな。
564:デフォルトの名無しさん
05/05/17 02:57:49
×メンテ不能
○俺に理解不能
565:デフォルトの名無しさん
05/05/17 07:37:28
あーあ、4,5,6って別々にするわけ?テンプレの意味ねー
566:デフォルトの名無しさん
05/05/17 07:41:46
テンプレートはマクロ
www.iba.k.u-tokyo.ac.jp/~yanai/template_tips.html
567:デフォルトの名無しさん
05/05/17 10:05:48
>>563
まあ同意。boostとか見てても思うが、言語使用の範囲内でどうにかしようとするから無理が出てくる。
パズルとしては興味深いが、無理やりやってるからどうしてもキモくなる。
新しいプリプロセッサ作ったほうがマシな気がする。
568:デフォルトの名無しさん
05/05/17 12:24:00
>>566
典型的なアホっぽいが。
exportはComeauでサポートされていることすら知らんようだし。
569:デフォルトの名無しさん
05/05/17 12:40:07
>>566
> まず最も重要な事実は、templateはマクロであるということである。
そもそも、始めの仮定についてキチンと論証してない時点でアウトだな。
570:デフォルトの名無しさん
05/05/17 13:16:28
templateはマクロだよ。
マクロと聞いてCやC++のプリプロセッサ(やVBAなどアプリケーション内のスクリ
プティング言語)しか思いつかない人に向けた文章ではなかろ。
571:デフォルトの名無しさん
05/05/17 14:01:12
>ここではオブジェクト指向に則ったよいtemplateの使い方を模索する。
この時点で道を誤っている気が。
572:デフォルトの名無しさん
05/05/17 14:29:53
templateの明示的インスタンス化なんて、少し考えれば
使い道などろくに無い機能だとわかるだろうに
しかも使う必要も無い機能だし
それにこだわってる時点で、ダメだなそのページ
573:デフォルトの名無しさん
05/05/17 18:56:42
ネタをまじめに叩くなよ
574:デフォルトの名無しさん
05/05/17 20:39:55
ねたじゃねーし
templateはコンパイルする前に展開されるからマクロなの
575:デフォルトの名無しさん
05/05/17 20:42:50
コンパイルする前に展開しちゃったら
タイプセーフは無理じゃないの?
576:デフォルトの名無しさん
05/05/17 20:47:38
いいよわからん奴は無理に使うな
577:デフォルトの名無しさん
05/05/17 21:03:14
マクロで使える構文を限定的にして型を認識させたのがテンプレート
578:デフォルトの名無しさん
05/05/17 21:12:28
みんな好き勝手に「マクロ」の意味を定義して使ってるから、話が噛み合わない
だけでしょ。
579:デフォルトの名無しさん
05/05/17 21:56:51
おっと、ここで578が正式にマクロの定義とやらを教えてくれるらしいぞ
580:デフォルトの名無しさん
05/05/17 22:03:42
なにこの意味不明な反応
581:デフォルトの名無しさん
05/05/17 22:21:02
付き合うだけ無駄でつ
582:デフォルトの名無しさん
05/05/18 07:21:54
普通のマクロでも引数の数を変えられるようなことはできないから
>>553
583:デフォルトの名無しさん
05/05/20 00:28:48
VC7.1で
std::list<int>使うとポインタの保存のためか
std::vector<int>の3倍近いメモリ使うんだが、
省メモリな実装のlistって無理なのかな?
584:デフォルトの名無しさん
05/05/20 00:55:57
>>583
SGI STLのstd::slistなら、一方向リストだけど、少しでも少ないかも。
585:デフォルトの名無しさん
05/05/20 01:45:41
リストすら作りを理解してないのかよ。
586:デフォルトの名無しさん
05/05/20 12:25:58
std::vectorのresizeコストが気になるようならstd:;dequeとか
587:デフォルトの名無しさん
05/05/21 00:07:18
つうか双方向リストは最低2つはポインタが必要なんだから当たり前の気がするんだが
588:583
05/05/21 00:47:56
サイズは可変で大きい、挿入削除が定数時間(->list)、省メモリ(->vector)
を同時に満たしたかったので...
とりあえず挿入削除の速いlistを選択したけど、以外とメモリ食うって分かった。
小規模のvectorをlistで繋ぐか584さんのslistつかうのがいい気がしてきた。
双方向リストだとポインタが64bit化したらさらに事態は悪化するのも気になるし...
589:デフォルトの名無しさん
05/05/21 00:53:20
だから小規模なvectorをつなぐぐらいならdeque使えってばよ
590:デフォルトの名無しさん
05/05/21 00:54:03
>>587
要素が int で、双方向のポインタがあるわけで
それぞれサイズが同じなら、int の 3倍ですね。
>>585 も指摘してますが、糞当たり前です。
591:デフォルトの名無しさん
05/05/21 00:54:46
>588
データ構造の勉強からやり直して来い。
592:デフォルトの名無しさん
05/05/21 00:55:27
s/int の/1要素あたり int の/
593:デフォルトの名無しさん
05/05/21 00:56:22
>>588
中身の小さいオブジェクトを入れると、相対的にlistはポインタなどの管理部分が
大きく見えてしまうからねえ。
ケースバイケースで使い分けるしかない。
それとstd::slistのiteratorは、forward iteratorなので、bidirectional iteratorのlist
に比べると実行効率の悪いメンバ関数がいくつか存在するから、その点もよく確かめてね。
594:583
05/05/21 01:04:49
dequeだと
中間への挿入、削除した場合に
参照と反復子が死滅。
595:デフォルトの名無しさん
05/05/21 01:05:46
>>588
テキストエディタみたいに、挿入が同一箇所に連続して発生するようなら
ギャップベクタを検討するといいかも
596:デフォルトの名無しさん
05/05/21 01:34:23
>>594
それが問題になるなら、もう list しかないんじゃないかなぁ。
「小規模のvectorをlistで繋ぐ」なんてのも、全然ダメだろ。
597:デフォルトの名無しさん
05/05/21 01:43:48
もはやtemplateの話題じゃなくて、「データ構造とアルゴリズム」の世界だな。
598:デフォルトの名無しさん
05/05/21 02:11:25
listとかvectorはあるのに、より優れた概念のS式がないのはおかしい
599:デフォルトの名無しさん
05/05/21 03:42:02
>>598
あなたね(汗
インタプリタじゃないんですから。
600:デフォルトの名無しさん
05/05/21 05:55:52
>>599
もっと詳しく。
・・・って言っても無駄か。
何もわかってないくせに噛み付いてるの見え見えだもんな。
601:デフォルトの名無しさん
05/05/21 08:25:20
S式ってツリー構造じゃ無かったっけ?違った?
602:デフォルトの名無しさん
05/05/21 08:41:31
>>600
赤黒木だけじゃ足りないってのかい。
603:デフォルトの名無しさん
05/05/21 09:18:31
>>597
STLネタがそっちに向かうのは自然だと思うけど?
604:デフォルトの名無しさん
05/05/21 09:22:59
> つうか双方向リストは最低2つはポインタが必要なんだから当たり前の気がするんだが
直前の要素のポインタと直後の要素のポインタの排他的論理和演算結果を保持しておけ。
そうしておけばポインタ1つで双方向からリストをたどることができる。
実行時にそれなりのコストはかかるが、、、
605:デフォルトの名無しさん
05/05/21 10:01:07
>>604
結局サイズは変わらないわけだが。
しかも「ポインタ同士のXOR」?ワケワカラン。
606:604
05/05/21 10:23:45
以下のようなリンクリストがあったとする。
A‐B‐C
この時、B のポインタ領域には &A ^ &C となる値がセットされることになる。
順方向でA、Bまで読み込んできた場合、Aのアドレスは判っているはず。
このため、&A ^ (&A ^ &C) を計算することでCのアドレスが取得できる。
同様に逆方向でC、Bまで読み込んでいる場合、Cのアドレスは判っているため、&C ^ (&A ^ &C) を計算することでAのアドレスが取得できる。
これが magic list というデータ構造。
607:デフォルトの名無しさん
05/05/21 10:35:12
>>606
代償としてイテレータのサイズが大きくなるから、使い道は微妙だけどな。
608:デフォルトの名無しさん
05/05/21 10:43:01
>>606
ふーん。
std::list の実装に使われてるのは見たこと無いんだけど、
標準コンテナの実装としては何か問題があるのかな?
と考えたら、イテレータを取得した後に要素の削除・追加をするとマズイような気がした。
609:デフォルトの名無しさん
05/05/21 10:44:00
>>604
リストを変更しないときのコストはたいしてかからないんじゃないか。
簡単なループの場合、movl (%eax),%eax が xorl (%eax),%eax になるだけだろう。
>>607
イテレータのサイズなんて問題になることがそうそうあるとは思えんが。
前後に追加削除があるとイテレータが無効になってしまうから
std::listとはコンパチにならなくなることの方がまだ問題になりそうだ。
610:604
05/05/21 10:50:55
>>607
イテレータのサイズとリンクリストに保持される各要素のデータサイズを同列で比較するのもどうかと思うが。
イテレータにポインタを2つほど追加したところで、8バイトしかサイズは増えない。
(処理が複雑化する分、イテレータオブジェクトのサイズはもう少し増えると思うが。)
しかし、双方向ポインタにしてしまうと、各要素毎に4バイトの投資が必要となる。
611:604
05/05/21 10:58:43
>>608>>609
確かにイテレータの取得後に前後の要素が追加削除されると痛い。
排他制御の問題を抱え込むから、std::list との互換性は考えない方が吉かと。
612:デフォルトの名無しさん
05/05/21 11:12:46
>>609
> 簡単なループの場合、movl (%eax),%eax が xorl (%eax),%eax になるだけだろう。
訂正。これ間違い。xor+mov*2(or xchg)になるな。
613:デフォルトの名無しさん
05/05/22 00:18:22
> サイズは可変で大きい、挿入削除が定数時間(->list)、省メモリ(->vector)
データの格納にset使うのってやっぱダメなのか?
setの中身はconst扱いだけど、外してswapして取り出して消して使ってるけど。
挿入時もヌルデータ入れて跡で要素をswapしてるんで無駄なコピーも出ない用に工夫して、、、
、、、、
vectorはサイズ増えると勝手に自分のコピー作るんで、reserveしなきゃならんので嫌だ。
lispは探索が遅いし。mapはそんなものに使うのもったいないし。
結論 : set使え!
614:デフォルトの名無しさん
05/05/22 00:31:16
setが泣いてるぞ
615:デフォルトの名無しさん
05/05/22 00:31:37
listのメモリ効率が気になるような状況でsetなんか使えるかよ
つーか、dequeって要素へのアクセスもそこそこ速くサイズ変更のコストも最小限なのになんで使われんのか。
616:デフォルトの名無しさん
05/05/22 03:41:02
>>615
dequeって要素へのアクセスもそこそこ速く
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
環境によってはlist並みに遅いわけですが何か?
OSやCPUは敢えて書かないが、STLportとかSTLportとかSTLportとか。
617:デフォルトの名無しさん
05/05/22 06:50:59
>>606
C++ でポインタにビット毎の論理演算なんて
吉外じみた真似、よく平気で出来ますね。
618:604
05/05/22 08:36:41
>>617
坊やだな、、、
ポインタと言えど所詮はビット列なのだよ。
619:デフォルトの名無しさん
05/05/22 08:39:59
>>618
reinterpret_castとか使わないといけないんだろ?
環境依存イクナイ(・A ・)!
620:デフォルトの名無しさん
05/05/22 08:55:43
>>606
面白いなぁ
621:604
05/05/22 08:55:52
>>619
reinterpret_castが即、環境依存につながるとは新鮮な考え方だな。
同じ環境内でキャストして、同じ環境内で元に戻すのであれば、環境依存も何もないだろうに(それを環境依存というのなら、コンパイラが吐くコードはすべて環境依存になるぞ)。
それとも、そういうことすら期待できない処理系が現存するというのか?
(そんなのが出てきた時点で reinterpret_cast は言語仕様から外されるだろうて。)
622:デフォルトの名無しさん
05/05/22 09:07:29
>>621
愉快な香具師だなお前。
C++の実装と進化の§14.3.3(P420)読んでみろ。
623:デフォルトの名無しさん
05/05/22 09:09:30
>>622
○C++の設計と進化
×C++の実装と進化
それから、規格票を優先しろ。
624:604
05/05/22 09:17:26
その本は持ってない。
引用の範囲内だろうから、出典を明記して引用してくれ。
内容を咀嚼して説明してくれてもよいぞ。
625:620
05/05/22 09:35:20
俺の面白いは純粋な意味であって、622と同じ意じゃないですよ
626:デフォルトの名無しさん
05/05/22 09:38:55
5.2.10 Reinterpret cast
4 A pointer can be explicitly converted to any integral type large enough to hold it.
The mapping function is implementation-defined [Note: it is intended to be unsurprising
to those who know the addressing structure of the underlying machine. ]
5 A value of integral type or enumeration type can be explicitly converted to a pointer.
A pointer converted to an integer of sufficient size (if any such exists on the implementation)
and back to the same pointer type will have its original value; mappings between
pointers and integers are otherwise implementation-defined.
要するに規格としてはポインタ型を整数型にreinterpret_castして
その値をそのままポインタ型に戻す操作以外は完全に実装依存
627:604
05/05/22 09:57:53
「5.2.10 Reinterpret cast」の真意は、整数型にキャストし、演算後の《変更された値》をポインタにキャストし戻したとしても、それはポインタとして無効であるということだけだと思うぞ。
一例を挙げると、配列の特定要素を指すポインタを整数型に変換した後、インスタンスオブジェクトのサイズ分だけ値を加算し、ポインタ型に戻したとしても、次の要素へのポインタにはならないぞ、、、という。
Magic listにおける A-B-C という例において、Bに保存されている値はAのアドレスとCのアドレスを特定のルールで「エンコード」しただけの整数値であり、デコードすることにより元々のポインタ値を復元することが可能なはず(てーか復元できなければ意味はない)。
このため、上記の§5.2.10の規則には抵触しないと思うが?
むしろ「A pointer *can be* explicitly converted to any integral type」と書かれている以上、そのことが保証されているとも取れる。
integral typeにして何の演算も許さず、元のポインタに戻すことしかできないのであれば、そもそもキャストする意味ないし。 まさかシリアライズするのか?、、、ってそれはあまりにも危険だしな。
628:デフォルトの名無しさん
05/05/22 10:18:14
>>626
ん?問題ないんじゃない?
同じポインタからは同じ整数になり、
同じ整数からは同じポインタになるっていう射影だよね。
この規格表のいいたいところは要するに、
アドレスが16違っている2つのポインタを、
整数に直した時も16違っているかどうかはわからないよ、
というだけの話じゃん。
629:626
05/05/22 10:20:55
>>627
>Magic listにおける A-B-C という例において、Bに保存されている値はAのアドレスとCのアドレスを特定のルールで「エンコード」しただけの整数値であり、デコードすることにより元々のポインタ値を復元することが可能なはず(てーか復元できなければ意味はない)。
>このため、上記の§5.2.10の規則には抵触しないと思うが?
>むしろ「A pointer *can be* explicitly converted to any integral type」と書かれている以上、そのことが保証されているとも取れる。
5.2.10/5はポインタを整数にreinterpret_castした後,その整数値を「そのまま何の演算も行わずに」
元のポインタ型に再度reinterpret_castした場合,元のポインタ値に復元されることを保証するものです.
604さんのmagic_listでは排他的論理和演算を取るため「そのまま」ではないものの
5.2.10/5は明らかにreinterpret_castによるpointer <-> integerの1対1写像を保証しているものと
読めるため確かにそのとおりですね.626は621に対する指摘のつもりでしたが,
いやはや指摘がまったく見当違いどころかむしろ621が正当である根拠になりえますね.
これまた大変失礼しました.
>>628
上に同じです.失礼しました.
630:デフォルトの名無しさん
05/05/22 12:18:47
magic list はネタとしては面白いが、現実には滅多に使われない
データ構造だな。この手のネタは Hakcer's Delight とか Knuth
センセの本を読むとイロイロ転がってるよ。
あと、現実のプログラミングだと、list に int 一個だけ入れるのも
珍しい気がする。手元のコードをいくつか見直してみたが、わりと
大きめの構造体を繋ぐか、スマートポインタを入れることが多い。
いずれにしてもポインタ二個分のメモリなんて誤差って感じ。
631:デフォルトの名無しさん
05/05/22 13:39:00
珍しいかどうかは、ともかく
メモリ云々行ってた奴は、たぶん初心者だから
初心者の戯言を、あまり真に受けないほうが
632:デフォルトの名無しさん
05/05/23 09:43:55
結論はvector使え、でいいのか?
633:デフォルトの名無しさん
05/05/23 09:54:29
>>632
いい
634:デフォルトの名無しさん
05/05/23 12:40:40
magic list は所詮オナニー
635:デフォルトの名無しさん
05/05/23 18:35:46
ここはジェネリックプログラミングの話題じゃないのか?
636:デフォルトの名無しさん
05/05/24 00:13:26
>>635
テンプレートの話題ですよ。尤も、スレタイも読めないなら
このレスも読めない可能性、大。
637:デフォルトの名無しさん
05/05/24 03:37:35
暇つぶしに作ってた、ヘボコンパイラは出来上がったから
今度は、マジックリストクラステンプレートでも作ってみようかな
作ったらほしい人いる?
638:デフォルトの名無しさん
05/05/24 08:09:05
>>637 興味はある
639:デフォルトの名無しさん
05/05/24 09:47:05
学術的な興味なら。
ソースより測定結果をみたい。listやvectorとの比較つきで。
640:デフォルトの名無しさん
05/05/24 15:44:00
というか作りかけてる・・・
641:デフォルトの名無しさん
05/05/24 22:41:55
できたら
>>639もぜひ。
642:デフォルトの名無しさん
05/05/24 23:45:11
>>640
637だけど、あなたに任せます
643:デフォルトの名無しさん
05/05/25 01:39:21
小規模だけど多次元配列のポインタがどうしても必要で、newも使いたくないから
std::vector<std::vector< ...> >
とかで書いてみたんだけど、4次元ぐらいからコンパイル時間が凄くかかる。
ま、コンパイル時に何がおきてるか想像すりゃ当たり前といえば当たり前だし、
コンパイル時だけの問題なので気にしなきゃいいんだけど、
環境になるべく依存しないで(boostとかは使えないし、VC,gcc両方通す必要あり)、
効率の良い方法がありまつかね。std::deque使ってもかわらなさそうだし。
644:デフォルトの名無しさん
05/05/25 01:49:02
>>643
その「多次元配列」のインターフェースを必要最小限に絞って、
pimpl なり抽象インターフェースなりでコンパイル単位を分ける。
基本だな。
645:デフォルトの名無しさん
05/05/25 02:06:06
>>644
㌧クス。
pimplイディオムは詳しくないので、Exceptional C++でも読んでみまつ。
646:640
05/05/25 02:46:33
URLリンク(kansai2channeler.hp.infoseek.co.jp)
面倒だったのでBoost使いました.1.32.0が必要です.すいません.
VC++7.1とGCC3.4.2(mingw)でコンパイル確認しています.
勢いだけで突っ走ったので激しく読みにくいコードで申し訳ないです.
イテレータが安定じゃないのでsplice系がイテレータ返さないと
使い物にならないので,イテレータ返すようにしてます.
std::listのインターフェースであと実装していないのはsortと演算子だけです.
でも今日はもう気力残ってません.パフォーマンス測定もしかりです.おやすみなさい.
647:デフォルトの名無しさん
05/05/25 04:02:34
void reverse() // throw()
{
head_ = decode(sentry_.code, head_);
}
感動してしまった。
648:デフォルトの名無しさん
05/05/26 03:43:21
URLリンク(kansai2channeler.hp.infoseek.co.jp)
微妙なバカチョンと例外飛んだときのバグを直しました.多分これで完璧なつもりです.
ただ,相変わらずsortだけ面倒なので実装してないです.
指摘されていたこととは言え,このデータ構造イマイチ利点がぼやけてますね.
特にアラインメントの関係でノードのサイズが普通のリストのそれと
同じになってしまう(32-bitマシンでmagic_list<double>とか)場合もあったりで散々かも.
唯一,647さんが指摘されているように要素順の反転を定数時間でできるのが
大きな特色ですけれど,それがうれしい状況ってあるんでしょうか・・・.
649:デフォルトの名無しさん
05/06/06 11:28:39
質問です。
「具現化によって生成された実体」 = 「ユーザー定義ではないスペシャライゼーション」
という理解でいいの?
650:デフォルトの名無しさん
05/06/07 22:08:43
"template テンプレート パラメータ"の意味が理解できないッス。
"Modern C++ Design" P11 の以下のコードなんですけど、
template <template <class> class CreationPolicy>
class WidgetManager : public CreationPolicy<Widget>
{
...
}
ここで template <class> に対して私の頭の中で
シンタックスエラーが発生します
。
template<class T> // ノーマル
template<> // 特殊化
template<class T=int> // デフォルト引数
template<class T, int=10> // 特殊化とデフォルト引数
というシンタックスは理解できています。
template <class> って何者? 誰か教えてください。
651:デフォルトの名無しさん
05/06/07 22:12:38
省略されてるだけ。
template <class /*T*/>
class foo;
652:デフォルトの名無しさん
05/06/07 22:27:41
>>651
サンクスです。とすると何らかの型を受け取るけど、
その型の情報は無視するよ、っていうことなんですね。
これをもとにもう一回読んでみます。
653:デフォルトの名無しさん
05/06/07 22:32:56
>>650
int f(int i);
int g(int); // これも脳内エラーが出るか?
654:デフォルトの名無しさん
05/06/08 00:28:08
>>650
例えば、
template< template<class T, class A> class Vector>
struct hoge
{
typedef T value_t;
};
typedef hoge<std::vector> hv_t;
としても、この時点では”T"はまだ決まってないわけだから
名前付けても使えないのです。
無論、”Vector"もこのままでは使えません。
実際の使用には
template< tempalte<class,class> class V>
struct hoge
{
template<class T,class A>
struct bind
{
typedef V<T,A> type;
};
};
typedef hoge<std::vector> hv;
typedef typename hv::template bind<int,std::allo..>::type
のように使うことになりますね。
655:デフォルトの名無しさん
05/06/08 00:31:15
補足ですが、
使えない == typedefできないということです。
656:デフォルトの名無しさん
05/06/08 00:41:11
>>654-655 とても650の理解を助けるとは思えない。
657:デフォルトの名無しさん
05/06/08 01:10:19
間違ったことは言ってないが、質問の答えとしては完全にズレてるな。
658:654
05/06/08 01:22:29
>>656-657
この場合
>"template テンプレート パラメータ"の意味が理解できないッス。
と書いてあるところから、名前云々は関係ないと思うのですが・・
659:デフォルトの名無しさん
05/06/08 10:35:01
>>658 会話になってないな。もういいから喋るな。
660:デフォルトの名無しさん
05/06/08 21:38:27
>>650です。
皆さんありがとうございます。
>>654さんのご意見もとても理解の助けになりました。
661:デフォルトの名無しさん
05/06/09 08:01:15
typedf templateってどうなったの?
662:デフォルトの名無しさん
05/06/09 08:13:16
template< template<class T, class A> class Vector>
struct hoge
{
typedef T value_t;
};
template<class B> typedef hoge<std::vector<B> > hv_t;
typeof(hv_t<int>::value_t) i;
みたいにtypedefの一文をテンプレート化できるんだっけ。
663:デフォルトの名無しさん
05/06/09 08:32:30
>>662
それはだめだろ。
template-templateパラメタのtemplateパラメタ(この場合T)
に言及するのは意味的におかしい。
664:デフォルトの名無しさん
05/06/09 08:43:39
こうじゃないか?
template <typename> struct hoge;
template <template <typename, typename> class V, typename T, typename A>
struct hoge<V<T, A> >
{
typedef T value_t;
};
template <typename T> typedef hoge<std::vector<T> > hv_t;
hv_t<int>::value_t i;
665:デフォルトの名無しさん
05/06/09 08:49:01
typedef templateを導入するなら変数templateや名前空間templateも欲しい。
と無責任に言ってみるテスト。
666:デフォルトの名無しさん
05/06/09 08:56:13
>>664
あーなるほど。C++よく分らないから適当に書いてみたんだけどそれなら理解できるw
>template <template <typename, typename> class V, typename T, typename A>
> struct hoge<V<T, A> >
こうやって部分的特殊化で各パラメータ間の関係を表現できるのね。
>>663
>template <typename T> typedef hoge<std::vector<T> > hv_t;
問題はこの部分で、パラメータvector<T>の高階性(?!)を維持してくれるのかどうかってところかねえ。
>>665
変数templateとはどんなもんでしょ?
667:デフォルトの名無しさん
05/06/09 11:34:08
もしも変数テンプレートがあったとしたらこんな感じ?
template <typename T> const T *NULL = 0;
int *pi = NULL;
char *pc = NULL;
#include <cstdio>
int main() {
std::printf("%p", NULL<void *>);
}
668:デフォルトの名無しさん
05/06/09 11:59:30
>>667
>int *pi = NULL;
>char *pc = NULL;
これを許すとまた規則が複雑になるな。
669:デフォルトの名無しさん
05/06/09 12:14:33
class null {
public: template<typename T> operator T*() const { return 0; }
};
const null NULL;
int *ip = NULL;
char *cp = NULL;
printf("%p", (void*)NULL);
でいいような気がす
670:デフォルトの名無しさん
05/06/09 12:16:52
誰もそんな話ししてないわけだが
671:デフォルトの名無しさん
05/06/09 13:24:53
>>667
引数とるコンストラクターはどうなるんだ。
672:デフォルトの名無しさん
05/06/09 13:52:48
typedef template ムチャ欲しいな。
673:デフォルトの名無しさん
05/06/09 14:26:04
>>667
今のC++の型の取り扱いにあわせると
template<typename T> const T *NULL = 0;
は,右辺がリテラルの0でこれは型がintだからポインタ型に変換できず,
Tをどの型でinstantiationすれば良いのか判断できずコンパイルエラーになる,
っていう扱いが妥当だと思いますよ.
もうちょい厳密に変数テンプレートを定義しようとすると,
結局,型推論のためのautoキーワードの拡張
auto a = b; // typename(b) a = b; の構文糖
と同じになると思います.Andrew Koenigあたりがこのautoキーワードの代わりに
>>667の構文を提案してたはず.
674:デフォルトの名無しさん
05/06/09 14:35:13
>>673
>>667の代わりに、
template <typename T> struct wrap{static const T *null;};
template <typename T> const T *wrap<T>::null = 0;
と書けることを考えると、今の扱いなら、
・template <typename T> const T *NULL = 0;
の時点では何も起こらない。
・printf("%p" NULL<void *>);
の点でインスタンス化が引き起こされ、void *const *を0で初期設定しようとし、成功。
が妥当じゃないのか?
675:デフォルトの名無しさん
05/06/09 14:50:45
>>670
そうでなくて、必要性が全く感じられないと言っている
まともな利用例ぐらい出さないと
676:デフォルトの名無しさん
05/06/09 14:56:07
>>674
その使い方だと常に明示的にインスタンス化しないといけない
(NULLを利用するたびに型パラメータを与えないといけない)わけですよね?
それは利用範囲が著しく限られませんか?
677:667
05/06/09 15:03:10
ところで俺は変数テンプレートは全く要らないと思うんだけどな。
俺も669と同じようなのを考えたことはあるけど。
678:デフォルトの名無しさん
05/06/09 15:10:28
>>676
使い道がないのは同意。
ただ、仮に現在のテンプレートの延長で「変数テンプレート」なるものを定義するなら、
>>674で言ったようになるはずだと思った。
>>673のような機能を導入するなら別の名前・構文を考えるべきだと思う。
679:デフォルトの名無しさん
05/06/09 15:26:38
型推論はされるとして、
NULLみたいに初期化子に使うとちょっと面白そうな…
クラス階層のあるところでPTHREAD_MUTEX_INITIALIZERみたいなやつ。
680:デフォルトの名無しさん
05/06/09 15:29:21
>>678
確かに「変数テンプレート」という名前は非常にまずいですね.
ただ構文については既存のキーワード使うとするとこれぐらいしかないような気がします.
681:デフォルトの名無しさん
05/06/12 15:01:48
アドビのオープンソースってど?流行ると思う?
STL、boostを基に、ウィンドウをスクリプトから生成する画期的システム
仮想マシンを実現とか、内容は理解を超えていた (つД`)
いわゆるチョット修正のときに威力を発揮すると思う
SEはどんな些細なこともPGに要望しなけりゃならない
PGは思いつきの修正のために仕事が増えるばかり
だれか人柱になってください、やっぱアドビ待ちなのかな
682:デフォルトの名無しさん
05/06/12 17:16:13
>>681
AdamとEve( URLリンク(opensource.adobe.com) )のことか?なかなか
普及は難しいんじゃないかなぁ…