• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:テンプレート仮想関数のようなもの)

仮想関数のテンプレート化に対するテクニックはあるか

rinkunの回答

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

マクロを使えば? 例えば #define VOPDEC(type) virtual operator type() = 0 struct HOGE{ VOPDEC(int); VOPDEC(short); //... }; #define VOPDEF(type) operator type(){return 0;} struct HOGE1 : HOGE{ VOPDEF(int) VOPDEF(short) //... }; とか。 イマイチやりたいことが見えないので、これで良いのか分かりませんけど。

haporu
質問者

補足

回答ありがとうございます。 やりたいことはvariant型のようなものを作ることです。 現在何の型を保持しているかという情報をvtblに任せるという方法をとってみようと思っています。 template<typename T = void> struct aconv; //基底 template<> struct aconv<void> abstract{ //ここでエラー template<typename U> virtual operator U() const = 0; }; //intなどの型用 template<typename T> struct aconv : aconv<>{ T v; aconv(const T &r) : v(r){} template<typename U> operator U() const{ return (U)v; } template<> operator str::string() const { /*数値から文字列への変換は後で実装*/ } //その他の型への変換 }; //特殊化1 template<> struct aconv<void*> : aconv<>{ typedef void *T; T v; aconv(const T &r) : v(r){} template<typename U> U conv() const{ return (U)(unsigned int)v; } }; //その他の特殊化(stringなど) template<> struct aconv<void*> : aconv<>{ ・・・ }; struct any{ //何らかのaconv<?>へのポインタ aconv<> *p; ~any(){ delete p; p = 0; } any() : p(0){} //ある変数の型のaconv<?>を確保してpに保持 template<typename T> any(const T &r) : p(new aconv<T>(r)){} template<typename T> operator T() const{ if(p){ return p->operator T(); }else{ return T(); } } //保持しているpを破棄して新しいaconv<?>を確保 template<typename T> any &operator=(const T &r){ aconv<> *tp = p; p = new aconv<T>(r); delete tp; return *this; } }; any a = 3; //代入は問題なくできるようになりました double b = a; // std::string c = a; // 仮想でないテンプレートoperator Uからテンプレートでない仮想関数などを呼び出して、どうにかして子クラスのテンプレート関数を呼ぼうかと思っていますが、型の情報をそのまま渡す手段がなくて、型を数値に変換して、数値から型を復元しようかと思いましたが、switch caseが多くなりすぎて困っています。 単純に変換を喜寿すると、caseの数が型数の2乗のオーダーになってしまうので、何とか型数の1乗のオーダーにして、特殊化が必要なstringなどを除いて、intやshortなどをできるだけ記述しないような方法を探しています。

関連する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)のようなこともできそうな感じがしたのですが、他に書き方があるのでしょうか。 どなたかご存知の方がいらっしゃいましたらご教示お願いします。

  • 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 の中に書くのも変な気がしました。

  • テンプレート指定クラスのコンストラクタを明示呼出

    自前でnewのような関数を作っています。 mallocで確保したメモリ領域のそれぞれの項目に対してコンストラクタを呼び出したいのですが、 テンプレートで指定されたクラスのコンストラクタを明示的に呼ぶにはどうしたらよいですか? テンプレート関数でなく、特定のクラスに対するものならできたのですが、 テンプレートで一般的に対応しようと思った所で躓きました。 また、deleteのほうは意図通り実装できました。 struct HOGE{ HOGE(){} }; //特定のクラスに対するものは正常 HOGE *mynew(size_t len){ HOGE *v = (HOGE*)malloc(len * sizeof(HOGE)); for(size_t t = 0; t < len; ++t){ //v[t].HOGE(); //error C2274: '関数形式のキャスト' : '.' 演算子の右側で使用できません。 v[t].HOGE::HOGE(); //OK } return v; } template<typename T> T *mynew(size_t len){ T *v = (T*)malloc(len * sizeof(T)); for(size_t t = 0; t < len; ++t){ v[t].T::T(); //error C2039: 'T' : 'HOGE' のメンバーではありません。 //代わりに以下のように書いてみたが若干危険で効率も悪そう T tmp = T(); memcpy(v + t, &tmp, sizeof(T)); memset(tmp, 0, sizeof(T)); } return v; } template<typename T> void mydelete(T *v, size_t len){ for(size_t t = 0; t < len; ++t){ v[t].~T(); //OK } free(v); } HOGE *h = mynew<HOGE>(3); //NG HOGE *j = mynew(3); //テンプレート関数でない方は呼べる mydelete(j, 3); //OK

  • 外部ファイルでのtemplate関数の実装方法

    外部ファイルでのtemplate関数の実装方法 sub.cppにtemplate関数を実装し、 main.cppで、sub.cppのtemplate関数を呼び出す、 みたいなことをやりたいのですが、 コンパイルは通りますが、リンクエラー?になってしまいます。 以下が上記のサンプルプログラムです。 //main.cpp #include <vector> #include <iostream> using namespace std; template <typename t_ret, typename t_array> t_ret sub_t(const t_array&); int main (int argc, char *argv[]) { vector<double> v; v.push_back(1.1); v.push_back(2.2); cout << sub_t<double, vector<double> >(v) << endl; return 0; } // sub.cpp #include <vector> using namespace std; template <typename t_ret, typename t_array> t_ret sub_t(const t_array& array) { return array[0]+array[1]; } //コンパイルログ main.o: In function `main': main.cpp:(.text+0x134): undefined reference to `double sub_t<double, std::vector<double, std::allocator<double> > >(std::vector<double, std::allocator<double> > const&)' collect2: ld returned 1 exit status make: *** [main] Error 1 どなたか、対処方法を教えてください。 宜しくお願いします。

  • テンプレート関数でコンパイルが通りません

    テンプレート関数でコンパイルが通りません いつもお世話になってます。テンプレート関数XXXで、引数のTYPE型によって、XXX内で呼び出す関数が変わります。以下の例では、eTypeがAならSetADataを呼び、eTypeがBならSetBDataを呼び出します。XXXのもうひとつの引数がテンプレート部です。本当は、rInfoの型(AInfoまたはBInfo)を判別できればeTypeは不要なのですが、判別の仕方がわからないので、eTypeでrInfoの型を伝えるようにしています。 template<typename T> int XXX( T& rInfo, const TYPE& eType ) if( eType == A ){   SetAData( rInfo ); else if( eType == B ){   SetBData( rInfo ); } // 明示的インスタンス生成 template int XXX<AInfo>( AInfo& rInfo, const TYPE& eType ) template int XXX<BInfo>( Binfo& rInfo, const TYPE& eType ) 上記のようにした時、コンパイラはTの部分をAInfoとBInfoの両方で解釈するので、どうしても以下のようなコンパイルエラーが出ます。 --- `int XXX(T&, const TYPE&) [with T = AInfo]': error: no matching function for call to `SetBData(AInfo&)' note: candidates are: int SetBData(BInfo&) `int XXX(T&, const TYPE&) [with T = BInfo]': error: no matching function for call to `SetAData(BInfo&)' note: candidates are: int SetAData(AInfo&) XXXをテンプレート関数でなく、明示的にAInfoとBInfoのオーバーロードにする手もあるかもしれませんが、XXXの中で、ここには載せていない大多数の部分は、まったく同じなので、テンプレート関数にするのが筋かなと思っています。このコンパイルが通るようにするには、どうすれはよいのでしょうか。

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

    テンプレートクラスに対して、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 に指定したいような状況が想像できません。

  • テンプレート関数

    template<typename Iterator, typename Type> void show(Iterator start, Iterator end) { ostream_iterator<Type> oi(cout, " "); copy(start, end, oi); } のように、関数の引数の型の数 (Iterator:1個)より、 テンプレートの数(Iterator,Type: 2個)が上回ってしまう場合、 この関数をどのように呼び出せばいいのでしょうか? 例えば、 vector<int> v; show(v.begin(), v.end()); ではエラーになります。

  • templateの使い方を教えて下さい。

    質問タイトルの通りです。 今、 unsigned char* AllocByteArray1d(unsigned long int n){ unsigned char *box; box = (uchar *)calloc(n, sizeof(uchar)); if(box == NULL){ puts("can't allocate memory..."); exit(1); } return box; } という関数があって、これはunsigned charの配列をとってくれる関数になってます。これをtemplateを使って、intの配列もとれるようにしたいんです。 恥ずかしながら試しに、 template <typename T> T* AllocByteArray1d(unsigned long int n){ T *box; box = (T *)calloc(n, sizeof(T)); if(box == NULL){ puts("can't allocate memory..."); exit(1); } return box; } とやってみましたがダメでした。事前にTのデータ型がわからないからだろうか、と思って template unsigned char* AllocByteArray1d(unsigned long int); を入れて実体化させてみましたが、これでもダメでした。 どこを修正すれば使えるようになるのか、C++に詳しい方に教えて頂けると幸いです。

  • テンプレートが複雑すぎる?

    以下のような文字列比較関数を作ろうと思っています。 ○配列変数であるときは配列版を、そうでないときはポインタ版を呼び出す  配列のサイズがわかるときは、仮に\0で終端していなくてもそれ以上検索しない ○charかwchar_tかを意識せずに使える ○charとwchar_tという記述ではなく、templateでできるだけジェネリック?的に記述したい //charを入れるとwchar_t、wchar_tを入れるとcharを返すメタ関数 template<typename T> struct invert{}; template<> struct invert<char>{ typedef wchar_t t; }; template<> struct invert<wchar_t>{ typedef char t; }; //同じ型同士の比較は省略 //A: 両方ポインタ template<typename T> bool compare(const T *const &v1, const typename invert<T>::t *const &v2); //B1: 左がポインタ、右が配列 template<typename T, size_t L> bool compare(const T *const &v1, const typename invert<T>::t (&v2)[L]); //B2: Tとtypename invert<T>::tを逆に template<typename T, size_t L> bool compare(const typename invert<T>::t *const &v1, const T (&v2)[L]); //C: 左が配列、右がポインタ //省略 //D: 両方配列 template<typename T, size_t L1, size_t L2> bool compare(const T (&v1)[L1], const typename invert<T>::t (&v2)[L2]); char aa[] = "abc"; char *pa = aa; wchar_t aw[] = L"abc"; wchar_t *pw = aw; bool c1 = compare(pa, pw); //A bool c2 = compare(pa, aw); //B1はC2784, B2なら可 bool c3 = compare(aa, pw); //C bool c4 = compare(aa, aw); //DはC2784 invert<T>::t (&v2)[L]という記述が複雑?なのかB1は呼べず、B2と記述すると通りました。 しかしDはどちらも配列であるため、B2のように回避できません。 オーバーロードを全て記述せずに、できるだけ簡単にすます方法はありませんか? 環境はVC++2010です。

  • C++テンプレートでの引数

     こんにちは。 今回は、C++ テンプレートで引数に構造体を使えないか悩んでいます。 例えば #include <stdio.h> typedef struct _rect{ int x; int y; }RECT; typedef struct _rect{ double x; double y; }DATA; template <calss T> T Function(T abc) { // 構造体の要素にも対応している。 cout << abc//の要素x << endl; cout << abc//の要素y << endl; return T; } int main() { RECT t; DATA r; t.x = 80; t.y = 90; t = Function(t); // こういった事をしたい r = Function(r); return 0; } というふうにしたいんです。 テンプレート関数に引数として構造体にしてそれぞれの要素を参照する場合はどうすれば よろしいのか教えてください。 よろしくお願いします。