【C++】template 統合 ..
[2ch|▼Menu]
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などアプリケーション内のスクリ
プティング言語)しか思いつかない人に向けた文章ではなかろ。




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

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