• ベストアンサー

C++ template operator T()

ソースを見ていて分からないところがあったので教えて下さい。 なんと説明すればいいのか分からないので下に要約したソースを書きます。 template <typename T> class Hoge { T a_; public: Hoge(T a = 0) : a_(a) {} operator T() const { // ココが分からない return a_; } }; 最初は、関数オブジェクトかと思ったのですがそうではないですよね? operator()(引数) ですよね? 次は、Tのコンストラクタかと思ったのですが、class Hoge の中に書くのも変な気がしました。

質問者が選んだベストアンサー

  • ベストアンサー
  • MrBan
  • ベストアンサー率53% (331/615)
回答No.2

それは、(templateに限らない)暗黙の型変換演算子定義です。 例えば、T=intの場合、 Hoge hoge; int foo = hoge; // ここでhoge::operator int()constが呼ばれる というようなことができます。 普通のクラスでも class Bar { int bar_; public:  operator int()const { return bar_; } // .... } 等が定義可能です。言語の参考書などを確認してみてください。

hi-mi-tsu
質問者

お礼

ありがとうございます。 うまく表現できないですが explicit で制限することの逆というか そういう感じですね。

hi-mi-tsu
質問者

補足

主にCをやってきた人間なのですが キャストが関数になるという、感覚がなかったです。 dynamic_cast,static_cast,reinterpret_cast,const_cast,boost::lexical_cast あたりもそうですね。 以下のようにすれば、複数キャストが作れますね。 あたりまえですが。 template <typename T, typename U> class Hoge { T a_; U b_; public: explicit Hoge(T a, U b) : a_(a), b_(b) {} operator T() const { return a_; } operator U() const { return b_; } }; int main() { Hoge<int, char*> a(4, "abc"); int x = a; char * y = a; ... }

その他の回答 (1)

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

Hoge を T に暗黙的にキャストするためのキャスト演算子の定義。

hi-mi-tsu
質問者

お礼

ありがとうございます。 やっと、意味が理解できました T が型名なので、キャストなんですね。

関連するQ&A

  • C++テンプレートクラスの内部クラスについて

    テンプレートクラスについていろいろ試していたところ以下のようなコードで struct A {     struct AA { };     operator A::AA() { return A::AA(); } // (1) }; template<typename T> struct B {     struct BB { };     template<typename U>     operator B<U>() { return B<U>(); } // (2)     template<typename U>     operator typename B<U>::BB() { return typename B<U>::BB(); } // (3) }; int main() {     static_cast<A::AA>(A()); // (1) ok     static_cast<B<int> >(B<short>()); // (2) ok     static_cast<B<int>::BB>(B<short>()); // (3) compile error     return 0; } (1)と(2)はできて(3)だけがコンパイルを通りませんでした。 試したコンパイラはVC9とg++(3.3.4)とbcc32(5.5.1)で、VC9では以下のようなエラーをはきました。 「error C2440: 'static_cast' : 'B<T>' から 'B<T>::BB' に変換できません。     with [ T=short ] and [ T=int ] コンストラクタはソース型を持てません、またはコンストラクタのオーバーロードの解決があいまいです。」 (1)と(2)ができれば(3)のようなこともできそうな感じがしたのですが、他に書き方があるのでしょうか。 どなたかご存知の方がいらっしゃいましたらご教示お願いします。

  • テンプレート引数の型推測

    コンパイラはVC++2008です。 いろいろあって、あるクラスにおいて関数ポインタと関数オブジェクト双方を 同じように利用できないかと考えて、次のように試みました。 class Base { public:     virtual void func() =0; }; template<class Func> class CFunc :public Base { private:     Func m_func; public:     CThreadFunc(Func func):m_func(func){}     void func(){m_func();} }; class Hoge { private:     Base* base; public:     template<class Func>     Hoge(Func func)       :base(new CFunc<Func>(func))     {}     ~Hoge()     {       delete base;     }     void DoSomething()     {       base->func();     } }; クラスをテンプレートにするといちいち指定しなければならないので、 まず基底クラスに適当な仮想関数を設け、それを継承したクラスをテンプレートにしました。 そしてコンストラクタの引数で何かしらを受け取って、オーバーライドした関数の中で 関数ポインタか関数オブジェクトだと仮定して呼び出しています。 さらに基底クラスのポインタを目的のクラスが保持してやり、 こちらはコンストラクタをテンプレートにすることで引数から型を推測してもらうことで 先ほどのテンプレートクラスのインスタンスを作成しています。 そしてポインタを介してfunc()を使ったり…、などすれば、 とりあえず引数なしの関数と関数オブジェクトを同等に扱えないかなと思ったからです。 で、このようなクラスを作成してコンパイルすると、 void func(); //何かしら処理する関数 class Function { public:   void operator ()();  //何かしら処理する関数オブジェクト }; があったとして、 int main() {   Function function;   Hoge hoge(function); //いったん作ってから渡す   Hoge hoge2(func); //関数を渡す     hoge.DoSomething();   hoge2.DoSomething();    } は動きました。しかし、 int main() {   Hoge hoge(Function()); //引数を初期化する } とすると次のようなエラーが出ます。 warning C4930: 'Hoge hoge(Function(__cdecl *)(void))': プロトタイプされている関数が呼び出されませんでした (変数の定義が意図されていますか?) また、 int main() {   Hoge hoge(Function()); //引数を初期化する   hoge.DoSomething();  //クラスにアクセス } とすると次のようなほかのエラーが出ます。 error C2228: '.DoSomething' の左側はクラス、構造体、共用体でなければなりません。 しかし、例えば関数オブジェクトのコンストラクタに引数が設定されていたとして、 class Function { public:   Function(int dummy);  //何か値を受け取る   void operator ()();  //何かしら処理する関数オブジェクト }; となっていた時、 int main() {   Hoge hoge(Function(1)); //引数を初期化する   hoge.DoSomething();  //クラスにアクセス } の呼び出しは正常にコンパイルされ、想定通りの動きをします。 全く使わなくても、一つ以上の適当な引数を何でもいいからコンストラクタが持てば、 普通にコンパイルされるみたいです。ただ、デフォルト引数を与えてHoge hoge(Function())と 同じ形ですと引数があってもできないみたいです。 まったく通らないなら最初からあきらめるですが、中途半端にちゃんと動くために エラーの原因を知りたいと思っています。 テンプレートの場合には、引数に渡すタイミングで初期化はしてはいけないのでしょうか?

  • テンプレート仮想関数のようなもの

    仮想関数をテンプレートにできないのは仕様と理解しているのですが、多少複雑になっても、それぞれの型に対するメンバ関数をいちいち記述していくことを回避するようなテクニックはありませんか? struct HOGE{ //template<typename T> //virtual operator T() = 0; //上記ができないので以下を全て記入していかなければならない virtual operator int() = 0; virtual operator short() = 0; //... }; struct HOGE1 : HOGE{ //template<typename T> //operator T() overtride{return T();} //上記ができないので以下を全て記入していかなければならない operator int(){return 0;} operator short(){return 0;} //... };

  • 「テンプレート」について

    C++でテンプレートについて調べています。 しかし、参考書や参考サイトを見ても下記の例のような、簡易な処理しか載っていないので、 実際にはどのような使われ方をしているのかわかりません。 例1)引数の大小を比較して、小さい方を返す。 template <class T> inline const T& btMin(const T& a, const T& b) { return b < a ? b : a; } 例2)引数の値を入れ替える処理 template <class T> inline void swap(T& a, T& b) { T temp = a; a = b; b = temp; } そこで、参考書や参考サイトなどでは載っていないような、 思いもよらない使われ方をしているものはご存じありませんか? できれば、使われているオープンソースの場所を教えて頂けると嬉しいです。 皆さんどうかよろしくお願い致します。

  • テンプレートクラス内のテンプレートクラス(インナークラス)のメソッドを実装ファイルで定義したい

    現在、ヘッダファイル内で下記のようなクラスを宣言・定義しています。 // test.h template < typename T1 > struct A {   template < typename T2 > struct B   {     B( A const& arg ) { ... }   }; }; テンプレートクラスが入れ子になっていて、Bのコンストラクタが引数としてAを取っています。 しかし現状ではコンパイルがとんでもなく遅くなってしまうので、 Bのコンストラクタは宣言のみとし、別途実装ファイル(test.cpp)に定義を書きたいと思っています。 ところがメソッドのシグネチャをどう書けばよいのか分からなくなってしまいました。 苦し紛れに // test.cpp template < typename T1, typename T2 > A<T1>::B<T2>::B( A<T1> const& arg ) { ... } などと書いてみましたが、違うようです。 解決方法はありますでしょうか? 環境はVC7.1かVC8でコンパイルできればよいです。 よろしくお願いいたします。

  • templateを使ったときの未解決の外部シンボルエラー

    以下のプログラムを、Visual C++ 2008でビルドすると、 『error LNK2019: 未解決の外部シンボル "class A<double> __cdecl add(class A<double> const &,double const &)" (?add@@YA?AV?$A@N@@ABV1@ABN@Z) が関数 _main で参照されました。』 のエラーになります。 template < typename T > class A { private: T x, y; public: A( const T& xx, const T& yy ):x(xx),y(yy){} T getx() const {return x;} T gety() const {return y;} friend A<T> add( const A<T>&, const T& ); }; template < typename T > A<T> add( const A<T>& a, const T& z ){ return A(a.x+z, a.y+z); } /* 直前のテンプレートでこの関数を作ったつもりです A<double> add( const A<double>& a, const double& z){ return A<double>(a.x+z, a.y+z); } /**/ #include <iostream> int main() { A<double> a(1.0, 2.0); double z=3.0; std::cout << add(a,z).getx() << "\n"; } どう書けばよいのでしょうか。

  • template<calss T> A(const T &t=T())

    template<class T> A(const T &t=T()); という関数宣言において引数のところの解釈に戸惑ってます どういう風に解釈したらいいのか教えていただければ幸いです

  • テンプレートクラス中のフレンドクラス

    下記をg++(fedora core1)でコンパイルしたところ、 #include <iostream> using namespace std; template< typename T > class A {   T a; public:   A(T aa ) : a(aa) { }   friend ostream& operator<<( ostream &os, const A &a ); //9行目 }; template< typename T > ostream& operator<<( ostream &os, const A<T> &a ) { return os << a.a; } int main( ) {   A<int>  a(5);   cout << a << '\n';   return 0; } 9行目にこのような警告・エラーが出てコンパイルできませんでした。(下記のオプションも試してみましたがダメでした) friend declaration 'std::ostream& operator<<(std::ostream&, const A<T>&)' declares a non-template function (if this is not what you intended, make sure the function template has already been declared and add<> after the function name here) -Wno-non-template-friend disables this warning. :undefined reference to 'operator<<(std::basic_ostream <char, std::char_traits<char> >&, A<int> const&)' なぜ、コンパイルできないのかが分かりません。ちなみに、bcc32(borland c++ compiler5.5.1)では同様のエラーが出てコンパイルできず、cl(VC++6.0)ではコンパイル・実行可能でした。 ご存知の方いらっしゃったらご教授お願いします。(bccとclはWinXPです)

  • template 参照 operator について

    「ゲームプログラマになる前に覚えておきたい技術」という書籍を読みながらC++でプログラミングの学習をしているのですが、template class と 参照 と operator の組み合わさったクラスでわからないところがあります。 自分で出来る限り調べてみましたが、解決できなかったので、答えていただけると幸いです。 Cの学習はひととおり済んでおりますが、まだC++は学習を始めたばかりなので理解が浅いです。 質問内容にいたらない点があるとは思いますが、お願いします。 以下のようなクラス定義文がありました。 template< class T > class Array2D{ public: Array2D() : mArray( 0 ){} ~Array2D(){ delete[] mArray; mArray = 0; } void setSize( int size0, int size1 ){ mSize0 = size0; mSize1 = size1; mArray = new T[ size0 * size1 ]; } T& operator()( int index0, int index1 ){ return mArray[ index1 * mSize0 + index0 ]; } const T& operator()( int index0, int index1 ) const { return mArray[ index1 * mSize0 + index0 ]; } private: T* mArray; int mSize0; int mSize1; }; この定義文の以下の部分 T& operator()( int index0, int index1 ){ return mArray[ index1 * mSize0 + index0 ]; } において、T&という記述がなければ、()という演算子のはたらきを再定義していて、 mArrayを2次元的に利用できるように値を返しているように見えるのですが、 T&がつくことによって、なにがどうなっているのでしょうか。 それと、参照というのは、利用するときには必ず初期化が必要、と学習したのですが、 この場合、初期化の処理になっているのでしょうか。 今までに出てきた参照では、簡単な例でいうと int n; int& m = n; というように、型名&別名=参照先 と、即初期化して使っていました。 これなら初期化されているのはわかりますが、今回のように、 「別名」の部分がoperatorになっていると、どのアドレスが「別名」が指すアドレスになるのでしょうか。 さっぱりわかりません。 質問の連続になってしまって申し訳ありません。 ほんとに困ってます。 おねがいします。

  • テンプレートクラスのフレンド関数の宣言

    テンプレートクラスに対して、operator << を定義しようとしてハマってしまったので。 ---- 最終的にできたコードはこんな感じ ---- template<size_t M> class MyContainer; template<size_t N> std::ostream& operator<<( std::ostream& os, MyContainer<N> const& cont ); template<size_t M> class MyContainer {  friend   ostream& operator<< <M>( ostream& , MyContainer<M> const& ); <= ここで「operator<<」としてハマった  public:   MyContainer() { }  private:   void Print_( std::ostream& os ) const {    copy( content_, content_ + M, ostream_iterator<int>( os, "\n" ) );   }  private:   int content_[M]; }; template<size_t N> ostream& operator <<( ostream& os, MyContainer<N> const& cont ) {  cont.Print_( os );  return os; } ------------------------------ テンプレートクラスのfriend関数を宣言する場合に、関数に明示的にテンプレート引数を与えないとテンプレート関数の特殊化だけが friend となるようです。 そういうもんだと言ってしまえばそれまでですが、何故こんな変態的な仕様になってるんでしょう? 特殊化された関数だけをテンプレートクラスのfriend に指定したいような状況が想像できません。