こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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 []' に変換できません。

とでてしまいます。
色々探してみたのですが、解決できませんでした・・。

特に最初のほうのエラーがよくわかりません。ちゃんと特殊化してる気はするのですが・・。

間違っている箇所の正当を載せていただけるとわかりやすくて、ありがたいです。
よろしくお願いします!

投稿日時 - 2010-05-15 16:15:56

QNo.5896847

困ってます

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

> template <class Type> Type minof(const Type x[], int n)
という形で作ることと、
> const  char *型に明示的に特殊化したもの
を作ることという要求に近いものとしては、

#include <iostream>
template <typename 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* const x[], 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];
for(int i = 0; i < n; i++){
std::cout << i + 1 << "番目---";
std::cin >> a[i];
}
std::cout << "文字列\n";
for(int i = 0; i < n; i++){
std::cout << i + 1 << "番目---";
s[i]=new char[64];
std::cin >> s[i];
}
std::cout << "整数の最小値---" << minof(a, n) << "です\n";
std::cout << "文字列の最小値---" << minof<const char *>(s, n) << "です\n";
}

とか?
> char s[n][64];
はテンプレートに合わせるためにchar*の配列に修正している。
各char*の領域はプログラムはすぐ終わるしnewしてdeleteはしてない。

あと、比較の不等号の向きは逆だと思うので反転している。
x[min]よりx[i]が小さいときに最小値を更新するのだと思う。

投稿日時 - 2010-05-15 21:25:14

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

ごめん、補足。
#include <cstring>
の抜けと
for(int i = 1; i < n; i++) if(std::strcmp(x[min], x[i]) > 0) min = i;
にしないと。
g++では特に何もしなくてもコンパイルできてしまったのでつい。

投稿日時 - 2010-05-15 21:39:25

お礼

おぉ・・strcmp関数は文字列の先頭のアドレスさえ渡せばいいから、わざわざ多次元配列で作らなくて、new演算子で先頭のアドレスだけ入手すればよかったんですね・・!

まさかこんなところでもnew演算子が役に立つとは思いもしませんでした。

あと、プログラム自体の間違いも指摘していただいて・・

ありがとうございました!

投稿日時 - 2010-05-16 00:58:56

ANo.3

間違ってたので修正のうえ再貼り付け。

#include <iostream>
#include <string.h>

using namespace std;

template <class Type> int less_than( Type x, Type y ){
cout << "DEBUG(G):" << x << "," << y << "=" << (x<y) << endl;
return x < y; }
int less_than( const char *x, const char *y ){
cout << "DEBUG(c*):" << x << "," << y << "=" << strcmp(x,y) << endl;
return strcmp( x, y ) < 0;
}

template <class Type> Type minof( const Type x[], const int n ){
int min = 0;
for( int i = 1; i < n; i++ ) if( less_than( x[i], x[min] ) ) min = i;
return x[min];
}

int main( int argc, char *argv[] ){
const char *a[] = { "test1", "test2", "t3", "test 4", "test No.5" };
cout << "Min of a:" << minof( a, sizeof a/ sizeof *a ) << endl;
const int b[] = { 3,4,2,1,5 };
cout << "Min of b:" << minof( b, sizeof b/ sizeof *b ) << endl;
}

投稿日時 - 2010-05-15 18:30:54

お礼

おぉ~、テンプレート関数の中にテンプレート関数を用いて、ムリに一つのテンプレート関数で実現しようとせずにしているわけですか!
この発想はありませんでした・・。

確かにこの方がテンプレート関数の引数が書きやすくていいですね!
なれない多次元配列の受け渡しなどをしてないから分かりやすいです

ありがとうございました

投稿日時 - 2010-05-16 00:52:41

ANo.2

特殊化というのは<class TYPE>のTYPEの部分がある型のときに処理を変えたいということなので、
template<class Type> Type minof(const Type x[], const int n)

TYPE部分をconst char*に変えても
template<> const char* minof<const char *>(const char x[][64], const int n)
にはならない。つまり、
template<> const char* minof<const char *>(const char x[][64], const int n)
の一般系(特殊型以外)の定義がないからエラーになるのだと思います。

例えば、
template<class Type> Type minof(Type x[], const int n)
template<> char* minof<char*>(char* x[], const int n)
ならエラーにならないはずです。
(ただし、上記の例をもちいるなら、関数本体も変えなければなりませんが・・・・・・)

投稿日時 - 2010-05-15 18:25:08

お礼

なるほど、特殊化にはそのような原理?みたいなものがあるんですね!
ただ単に上のテンプレート関数と同じ名前をしていたら、あとは引数の型とかは自由だと思ってました・・・。

分かりやすく教えてくださってありがとうございました!

投稿日時 - 2010-05-16 00:45:46

ANo.1

一例

#include <iostream>
#include <string.h>

using namespace std;

template <class Type> int less_than( Type x, Type y ){ return x < y; }
int less_than( const char *x, const char *y ){
cout << "DEBUG:" << x << "," << y << "=" << strcmp(x,y) << endl;
return strcmp( x, y ) > 0;
}

template <class Type> Type minof( const Type x[], const int n ){
int min = 0;
for( int i = 1; i < n; i++ ) if( less_than( x[min], x[i] ) ) min = i;
return x[min];
}

int main( int argc, char *argv[] ){
const char *a[] = { "test1", "test2", "t3", "test 4", "test No.5" };

int n = sizeof a / sizeof *a;
cout << "Min of a:" << minof( a, n ) << endl;
}

投稿日時 - 2010-05-15 18:19:36

あなたにオススメの質問