テンプレート関数の引数の型の数とテンプレートの数の不一致によるエラー

このQ&Aのポイント
  • テンプレート関数の引数の型の数とテンプレートの数が一致しない場合、エラーが発生します。
  • 解決策としては、テンプレート関数の呼び出し時に正しい型を指定する必要があります。
  • 例えば、vector<int>の要素を表示する場合は、show(v.begin(), v.end())と呼び出します。
回答を見る
  • ベストアンサー

テンプレート関数

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()); ではエラーになります。

  • J_H
  • お礼率42% (6/14)

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

  • ベストアンサー
  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.1

こうかな? show<int>(v.begin(), v.end()); 試してないので的外れでしたらすみません。

参考URL:
http://www.mamezou.com/tec/equip001.htm
J_H
質問者

お礼

型パラメータが明示できるんですね。 この辺は手元の本にも載ってませんでした。 template<typename Iterator, typename Type> だと show<int>(v.begin(), v.end()); はエラーになりましたが、 template<typename Type, typename Iterator> にすることで期待したものになりました。 ありがとうございました。

関連するQ&A

  • テンプレートについて

    最近テンプレートを勉強し始めました。 試しに次のような関数を書いたのですがコンパイルエラーが出ます。 template<class T> void pirntAll(T t) { T::iterator p; for(p=t.begin();p!=t.end();p++) cout<<*p<<" "; cout<<endl; } エラーメッセージを見るとT::iterator p;のところがダメらしく pが定義されていないと叱られます。 結局本などを参考にして次のように書き換えました。 template<class InputIterator> void printAll(InputIterator first,InputIterator last) { while(first!=last) { cout<<*first<<" "; first++; } cout<<endl; } しかしprintAll()を使うとき1つめの定義ならprintAll(x);と書けますが 2つめの定義だとprintAll(x.begin(),x.end());と書かなくてはならないので 面倒です。そこで2つめの定義と次の関数を組み合わせることで、コンパイルも通り、 使うときもprintAll(x);と書けるようにしました。 template<class T> void printAll(T t) { printAll(t.begin(),t.end()); } 一応問題は解決したのですが何かひどく冗長なことをやらされているようで 気分が悪いです。なんとか1つめのような書き方ができないものでしょうか。 または1つめの書き方が出来ない(T::iteratorが使えない)正当な理由が あるなら教えてください。

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

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

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

    下記を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関数の実装方法

    外部ファイルでの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 どなたか、対処方法を教えてください。 宜しくお願いします。

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

    以下のような文字列比較関数を作ろうと思っています。 ○配列変数であるときは配列版を、そうでないときはポインタ版を呼び出す  配列のサイズがわかるときは、仮に\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++の関数テンプレートで分からないところがあります。 C++の入門書を読んで勉強しているのですが、その演習問題(答えはついてないです)で、以下のような問題がありました。 ----------------------------------------------------- 配列の全要素の最小値を求める関数テンプレートを作成せよ。 teplate <class Type> Type minof(const Type x[], int n); という形で作ること。 なお、最も小さい文字列を求められるようにするために、const char *型に明示的に特殊化したものも合わせて作成すること。 ------------------------------------------------ という問題なのですが、これにたいして僕は以下のように答えました。ヘッダのインクルードなどは省きます。 template<class Type> Type minof(const Type x[], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(x[min] < x[i])             min = i;     return x[min]; } template<> const char* minof<const char *>(const char x[][64], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(strcmp(x[min], x[i]) < 0)             min = i;     return x[min]; } int main() {     const int n = 5;     int a[n];     char s[n][64];     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> a[i];     }     cout << "文字列\n";     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> s[i];     }     cout << "整数の最小値---" << minof(a, n) << "です\n";     cout << "文字列の最小値---" << minof<const char *>(s, n) << "です\n"; } これをコンパイルすると、エラーで 明示的な特殊化; 'const char *minof<const char*>(const char [][64],const int)' は関数テンプレートの特殊化ではありません と 'minof' : 1 番目の引数を 'char [5][64]' から 'const char *const []' に変換できません。 とでてしまいます。 色々探してみたのですが、解決できませんでした・・。 特に最初のほうのエラーがよくわかりません。ちゃんと特殊化してる気はするのですが・・。 間違っている箇所の正当を載せていただけるとわかりやすくて、ありがたいです。 よろしくお願いします!

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

    テンプレート関数でコンパイルが通りません いつもお世話になってます。テンプレート関数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の中で、ここには載せていない大多数の部分は、まったく同じなので、テンプレート関数にするのが筋かなと思っています。このコンパイルが通るようにするには、どうすれはよいのでしょうか。

  • STL に適合するようにクラスを書くとき皆さんはどうしているのでしょう

    大した質問ではないのですが、例えば適当に vector っぽいクラスを template<typename T> class HeppokoVector { private:  いろいろ省略 public:  void push_back(T const& val); }; のように設計したとしましょう。ヘッポコとは言え vector なので STL の std::copy を使って、HeppokoVector<char> hoge; に既存の vector<char> foo; の内容を std::copy(foo.begin(), foo.end(), std::back_inserter(hoge)); な感じでコピーしたいと思いましたが、コンパイルすると 「reference : は HeppokoVector<T> のメンバーではありません」 などと怒られます。back_insert_iterator の定義を見れば、reference や const_reference の定義が必要なので、 template<typename T> class HeppokoVector { private:  いろいろ省略 public:  typedef T& reference;  typedef T const& const_reference;  void push_back(T const& val); }; な風に修正するわけですが、皆さんは自前でコンテナを作る時などに、あらかじめ「コレコレの typedef は必要だな」とか知った上で作成しとるのでしょうか? きっと私が適当なだけなのでしょうが、back_insert_iterator のドキュメントを見ても、push_back が必要であることしかわかりませんでした。

  • listをvectorにコピーするときに

    例えば #include<iostream> #include<vector> #include<list> using namespace std; void main(void) { unsigned pos; list<unsigned> lu; list<unsigned>::iterator p; vector<unsigned> vu; for(lu.clear(),pos=0;pos<9;lu.push_back(pos++)); for(p=lu.begin();p!=lu.end();cout<<*p++); cout<<endl; vu=vector(lu); //error for(pos=0;pos<vu.size();cout<<vu[pos++]); cout<<endl; } とするとエラーになるため//errorのかわりに vu.clear(); vu.insert(vu.begin(),lu.begin(),lu.end()); としていますが少し不細工です 他に方法はあるのでしょうか?

  • STLのvectorの削除

    STLのvectorの削除を行う場合に vector<myclass> v; ・・・ v.erase(it); ・・・ というように削除するiteratorを渡しますが、 任意のインデックスのvectorを削除した場合は、 どのようにそのiteratorを取得するのでしょうか。 例えばv[5]を削除したのですが、 vector<myclass>::iterator it=v.begin(); for(int i=0;i<5;i++) it++; v.erase(it); というbegin()やend()からのインクリメント・デクリメントで取得するしかないのでしょうか? ご教示願います。