Generic Programming with C++ Template
MinGW(gcc3.2)でもやはり redifinitionエラーが出ます。同名の関数オブジェクト
は使えないなんて初めて知った(汗。
>>926 参照を渡すときのFnの実体化は、Fn<Foo> f; ですか Fn<Foo&> f; ですか?
とりあえず後者は通らないようです(gcc3.2)
いや、pointer<>は T* を保持するんだから、Tは * やら & つけちゃだめか。
スマソ。
できました。サンクスコ。
禿げしくコンパイル時間が延びたような気もするが・・
うぅぅ〜。。。typedefのtemplateはダメなのかよぉ…。
template <template<class> class T>なクラス←なんて言うんだ?
を書いてみたものの、bccだと型変換演算子でコケて、
gccだとstd::vectorで特殊化した方のクラスの演算子でコケる…。。。
(−_−)
(∩ ∩)
943 :
デフォルトの名無しさん:02/10/10 13:13
http://sourceforge.net/projects/loki-lib/ ここから落とした最新のLoki+テストコードを使っています。
コンパイラはg++3.2です。
Loki/tools/RegressionTest/Test_MultiMethods.cpp
このテストプログラムにおいてよく分からないことが
あるので教えてください。
場所はBasicDispatcherをテストしている160行目あたりの
ShapeDispatcherAddというテンプレート関数です。
ここで関数の引数として取得したディスパッチャーインスタンスの
Addテンプレート関数を呼んでいるのですが、
この関数のテンプレートパラメータはどこで指定すれば
よいのでしょうか?。テストコードでは(通常の関数テンプレートと
同じように)メソッドをコールする時点において指定していますが
どうもこれが上手くいっていないようです。
x.Add<Shape1,Shape2>(HatchDispatcher<Shape1,Shape2>);
という行で、既にインスタンス化されたテンプレートクラス内の
関数を実体化するはずなのですが、これがコンパイラエラーと
なります。
x.Add()(HatchDispatcher<Shape1,Shape2>);とテンプレートパラメータ
の指定を取り除くとエラーは消えます。
なにか問題を回避するような方法があれば教えてください。
訂正です
x.Add()(HatchDispatcher<Shape1,Shape2>);
ではなくて
x.Add(HatchDispatcher<Shape1,Shape2>);
でした
945 :
デフォルトの名無しさん:02/10/10 14:14
>>941 どんなのが駄目なの?
いま漏れも
typedef boost::tuple<const int, const std::string, const std::string> hoge;
がVCでのみ通らなくて困ってるんだけど。
#スレ違いの予感
エラーの原因を突き止めるため単純化したプログラムを
一つ作ってみました。
template<class T> class CLS{
public:
template<class U>
void memfunc(){U i;}
};
template<class T>
void func(T& a){
a.memfunc<int>(); //これがどうもおかしい
}
int main(){
CLS<int> a;
func(a);
}
これを回避するためにはどうすればいいのでしょう?
template<class T> class CLS{
public:
template<class U>
void memfunc(){U i;}
};
int main(){
CLS<int> a;
a.memfunc<int>();
}
このようにパラメータとしてやり取りするのを省けば
上手くいくのですが。。。
>>942 g++ でダメな演算子ってどんなの?
まあ、なんにしても VC++ じゃ通らないから仕事では
避けざるをえないんだけどね。
やっぱり仕様書をよく覚えないとダメだね、こりゃ。
いままで仕様書見てプログラミング言語覚えたこと
なかったからどうも抵抗があったんだけどそうも
いってられなさそう。。。
14882の14章をよく読んできます。
>>946 これは、template 限定子ってのが必要になるケースだね。
template<class T>
void func(T& a) { // ここでは a がどういう型か分からないので
a.template memfunc<int>(); // このように memfunc がテンプレートであることを明示する
}
これで 950 レス目だけど、次スレはもう不要でしょ。
とりあえずは STL スレか Boost スレを使うことにして、
いずれは 「C++ Template & Libraries (STL, Boost, Loki, etc.)」
みたいな形で統一しましょう。
>>949 素晴らしい!素晴らしすぎます!!!
どうもありがとうございました。
どうしてそんなことを知っているのでしょうか?
"C++""限定子"で検索かけても一つ引っかかるだけ。。。
C++は奥が深いですね。
ちなみにテストコードは以下のようになりました。
template<class T> class CLS{
public:
template<class U>
void memfunc(U&){U i;}
};
template<class T>
void func(T& a){
// a.template memfunc(a); //テンプレート関数の型推論を試すその2。error
a.template memfunc<T>(a);
}
int main(){
CLS<int> a;
func(a); //テンプレート関数の型推論を試すその1。ok
}
型推論の機構もあわせてもう少し調べてみます。
ありがとうございました。
>>951 Borland-C++5.5.1だとtemplate限定子がなくても通ってしまうね。
でもgcc3.2だとエラーが出る。
プログラミング言語C++第3版§C.13.6、P971によるとmemfuncの
テンプレート引数は予測不能なので、"<"が比較演算子だと誤認
されエラーが出るようだ。
>>952 プログラミング言語C++はそんなことまで載って
いるんですね。私はC++Primerで勉強しているのですが
そんな記述あったかしら??。帰って読み直してみます。
ちなみにCLSはpublicのメンバーしかないから
structとすべきですね。こういう細かなルールは
大事にしたいものです。。
>>950 次スレは要らないでしょうね。Lokiはもう一般的に
認知されたと思っていますので、特別に扱うのも
なにか違うかなとおもいます。
boostスレで十分でしょう。ちなみに私の質問は
相談室の方ですべきでした。すみませんm( )m
Lokiのダブルディスパッチャ(<Loki/MultiMethods.h>)に関して
疑問があります。
class FnDispatcherなのですが、このクラスは三つのAdd()関数を
持っていますが引数のないAddが二つ含まれています。
これってオーバーロードできずにコンパイルエラーになると
思うのですがどうでしょうか?
一つは対照ディスパッチャ(二つの要素の順序関係なし)として
機能するようにbool型のフラグ(bool symmetric)を受け付けるように
定義されていますが、そもそも関数の部分的特殊化は出来ないはずですよね?
これはg++-3.2では"cannot be overloaded"というエラーが出ます。
これはコンパイラの構文解釈としては正しいと思われますが、
なぜかg++-2.95では通ってしまうんですね。。
ライブラリのバグでしょうか?それとも私の何勘違いでしょうか?
また、正しくオーバーロードが行われるように、
対照ディスパッチャの引数としてAdd(bool)などという
ものを加えれば正しく動作するのですが、これって
なんかカッコ悪いですよね。汗
コンパイル時にだけしか使わない情報はなるべくテンプレート
パラメータとして渡したいところです。
template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&),
bool symmetric>
void Add()
{
typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs,
SomeLhs, SomeRhs,
ResultType,
CastingPolicy<SomeLhs,BaseLhs>,
CastingPolicy<SomeRhs,BaseRhs>,
callback> Local;
Add<SomeLhs, SomeRhs>(&Local::Trampoline);
if (symmetric)
{
Add<SomeRhs, SomeLhs>(&Local::TrampolineR);
}
}
そもそも対照性を持つ場合はこのようなコードになっているので、
単にAddのテンプレート引数symmetricにデフォルト値として
falseを与えればいいように思うのですが、それだと困るような
コンパイラがあるのでしょうか?
template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&),
bool symmetric = false>
void Add()
Loki のことは全くわからないんだけど、関数の部分的特殊化は
可能のはず。VC++ みたいにできないコンパイラもあるけど。
>956
関数テンプレートでは、デフォルトのテンプレート引数は使えないはず。
あ、勘違いしてました。。。恥
FnDispatcher::Add()は部分的特殊化ではなくて、
一次テンプレートが二つあるんですね。
んー、そうするとAddが二つあるのはいいんだろうか?
>>957 ModernC++DesignのP30には
「残念なことに、テンプレートの部分的特殊化は、メンバ関数、
非メンバ関数を問わず、関数には適用されません。」と書いてあります。
例として、
template <class T, class U> T Fun(U obj); //一次テンプレート
template <class U> void Fun(U obj); //部分的な特殊化(不正)
template <class T> T Fun(Window obj); //オーバーロード(正当)
というものが挙げられています。
関数テンプレートのデフォルト引数には関しては、、、調べてみます。
template <class U> void Fun(U obj); //部分的な特殊化(不正)
この行は間違いでした。書きたかったのは、
template <class U> void Fun<void, U>(U obj); //部分的な特殊化(不正)
です。失礼しました。
あ、おそかったかw
すまん、関数テンプレートの部分特殊化はダメだったかもしれない。
多重定義は可能なので部分特殊化ができていると勘違いした。
毎度、スレ汚しすみませんが簡単なテストプログラムです。
#include<iostream>
template <class T> struct CLS
{
template <class U, class R>
void Add(){std::cout << "二つのテンプレートパラメータの関数" << std::endl;}
template <class U>
void Add(){std::cout << "一つのテンプレートパラメータの関数" << std::endl;}
};
int main(){
CLS<int> a;
a.Add<int, int>();
a.Add<int>();
}
これがg++-2.95だと通ってしまうんですね。g++-3.2によるエラーは以下の通りです。
test2.cc:8: `template<class U> void CLS::Add() [with U = U, T = int]' and `
template<class U, class R> void CLS::Add() [with U = U, R = R, T = int]'
cannot be overloaded
そもそも一次テンプレートを二つも定義できてしまうのはやはり問題で、
それに増して、テンプレート引数の数による部分的特殊化が出来てしまうのは
ちょっと。。。動作としてはg++-3.2の動作が正しいと思うのですがどうでしょうか?
また、もしそうだとするならこれはLokiのバグですよね?
>>957さん
何か資料に当たったわけではないのですが、
テンプレート関数のテンプレートパラメータには
デフォルト引数は設定できないです。
g++の3.2,2.95のどちらも
"default argument for template parameter"
と返してきます。
勉強になりました。ありがとうございます。
ちょっと気になったので、規格書を調べてみた。
●関数の部分的特殊化は不可
14章冒頭の2
a function template declaration, the declarator-id shall be a template-name
(i.e., not a template-id).
つまり、template<class T> void foo<T>(); のように <T> を付けた宣言は
できないということ。(ただし explicit specialization の場合は可)
●関数テンプレートではデフォルトのテンプレート引数を使えない
14.1 の 9
A default template-argument shall not be specified in a function template declaration
or a function template definition, nor in the template-parameter-list of the definition
of a member of a class template.
●テンプレート引数が異なっていれば、戻値やシグネチャの一致する関数テンプレートの
オーバーロードは可能
14.5.5.1 の 4
The signature of a function template consists of its function signature,
its return type and its template parameter list. The names of the template parameters
are significant only for establishing the relationship between the template parameters
and the rest of the signature. [Note: two distinct function templates may have identical
function return types and function parameter lists, even if overload resolution alone
cannot distinguish them.
template<class T> void f();
template<int I> void f(); // OK: overloads the first template
// distinguishable with an explicit template argument list
実際、g++-3.2 でも非メンバ関数テンプレートならオーバーロード可能だった。
なるほど、どうもありがとうございます。
とくに三つ目の件に関しては勉強になりましたm( )m
●1つ目
explicit specializationとは完全な特殊化という意味ですよね?
template <class T> T foo();
template <> int foo<int>(){};
template <> double foo<double>(){};
というような。。
●3つ目
以下のようなコードはg++-3.2,2.95どちらでもOKでした。
namespace{//無名名前空間の外でも同じでした。
template<class T> void func(){cout << "<class T>" << endl;}
template<int I> void func(){cout << "<int I>" << endl;}
template<class T,class U> void func(){cout << "<class T,class U>" << endl;}
template<class T,int I> void func(){cout << "<class T,class int>" << endl;}
}
int main(){
func<int>();
func<8>();
func<int,char>();
func<int,3>();
}
ということはg++-3.2のテンプレートメンバ関数の解釈はどうなんでしょう?
g++のバグということになるんでしょうかね??
補足ですが、クラスに関して同じようなことは当然×みたいですね。
struct CLS;
template <class T> struct CLS;
template <class T, class U> struct CLS;
こういうのは当然のごとくエラーになりますね。
previous declaration `template <class T> CLS<T>'といったかんじのメッセージがでます。
関数テンプレートが部分的特殊化が許されていない分、ユーザーに対して
サービスしてくれたのかな(藁
というよりも考え方としてはオーバーロードの延長として見るべきでしょうかね。
クラスは原則として名前が一意に決定されていなくてはならない。だけどそれでは
コンパイル時にクラスの選択をさせることができない。原則を守りつつの追加という形で
explicit specialization, partical specializationがそれぞれ可能になっている。
関数にはもとからオーバーロード機能が付いていたので、その機能を補う形で
一次テンプレート(というよりも関数テンプレートには一次しかない。完全な特殊化は
どちらかというと実体化っていうかんじかな)でのオーバーロードと
explicit specializationの二つの機能が付いたという。。。
C++を勉強していていつも思うのが、なんでそういう仕様になっているのかという
その理由の分からなさのこと。どういった事情からそういう仕様になっているのか
まとめてあるようなドキュメントが読みたいです、というよりその前に英語の仕様書を
なんとか読まなくてはいけないのですが。。。はぁー
>949
いいことしった(・∀・)!
967 :
デフォルトの名無しさん:02/10/20 17:15
アリガトウ-
971 :
デフォルトの名無しさん:02/10/20 18:29
>>968 これ売り物?
ダンロードできないんですが。
コンパイラのバックエンドを作成している企業にしか販売してませーん
ということじゃないかなぁ。
ありがとう。
やっぱ売り物なのね。
http://www.edg.com/faq.html > Q: How much does a source code license cost?
>
> A: Usually somewhere between $40,000 and $250,000. There are
> lots of different kinds of licenses, so you'll have to contact us
> to get a specific quote.
ちょっと個人では手が出しにくいお値段だぁね。
gcc3.2でいいやぁ・・
VCに使えばいいのに
>>977 このスレではVCは出入り禁止ですが何か・・・・?
梅梅
980ゲット
981 :
デフォルトの名無しさん:02/10/28 18:51
このスレも埋め立てるだけか。
C++スレは少し減らした方がいいと思われ。
記念パピコV(^o^)V
という訳でLokiネタもboostスレへと殴りこみに入ります。
みなさん一年間どうもありがとうございました。
梅うまうま