3

関数のテンプレートに取り組んでいました。簡単にするために、次のようになります。

template < typename T >
void f(const T & x)
{
    cout << "generic case" << endl;
    cout << x << endl;
}

私は常に、C 文字列をテンプレート パラメーターの引数として使用できないと考えていました。しかし、以下は実際に機能します (g++ 4.5.1 を使用):

f("hello world");

私の質問は次のとおりTですf("hello world")

正確に何が起こっているのかを特定しようとしました。たとえば、私char[]const char*これを見たので(明らかに機能しません):

template < typename T >
void f(const T & x)
{
    cout << "generic case" << endl;
    cout << x << endl;
}
template <>
void f(const const char * T & x)
{
    cout << "char[] case" << endl;
    cout << x << endl;
}

いくつかのバリエーションを試しました。それらのどれも機能しません。

ASIDE:私がやっていることには、これは本当に必要ありません。T = "C-string" の場合の特殊化が必要なので、別のテンプレート関数を書きました:

template < typename T >
void f(const T & x)
{
    cout << "generic case" << endl;
    cout << x << endl;
}
template < typename T >
void f(T x[])
{
    cout << "T[] case" << endl;
    cout << x << endl;
}

正確に何が起こっているのか、私が読んだことではできないと言われているのに、なぜC文字列をテンプレート引数にすることができるのか知りたいので、私はただ尋ねています。テンプレートについて読み間違えた/誤解したに違いありません。

4

2 に答える 2

3

Cストリングタイプはありません。C-string という用語は、型ではなく内容を定義します。これは、文字列の末尾を意味するように一部の関数によって解釈される null 文字を含む文字配列の一部を指します。

あなたが本当に興味を持っているのは、文字列リテラルです。文字列リテラルの型const char[N]は です。ここで、N は文字列内の文字数であり、暗黙的な null ターミネータを含みます。"hello world"タイプもそうですconst char[12]。次のように特化できます。

template<>
void f(const char(&x)[12])
{
   cout << "const char[12] case" << endl;
   cout << x << endl;
}

これはサイズ 12 の配列のみをカバーすることに注意してください。ただし、次のようにすべてのサイズf()に対して(特殊化ではなく) オーバーロードできます。

template<size_t N>
void f(const char(&x)[N])
{
    cout << "const char[" << N << "] case" << endl;
    cout << x << endl;
}

また、これらのメソッドは通常の名前付き配列もカバーすることに注意してください。それらと文字列リテラルを区別する方法はありません。

于 2013-03-28T04:37:31.203 に答える
0

これは const char[N] と const char* の両方が推測するように機能することに注意してください。

template < typename T >
void f(const T* x)
{
    cout << "const char* case" << endl;
    cout << x << endl;
}

ここでの特殊化は、定数ポインター型です。

char 配列型またはポインター型に基づく特殊化が必要な場合は、単純な関数のオーバーロードも使用できます。

于 2013-03-28T05:48:55.910 に答える