1

次の関数が定義されています。

template <typename T> buffer_t &operator<<(buffer_t &buffer, T data);
template <> buffer_t &operator<<(buffer_t &buffer, const char *data);
template <> buffer_t &operator<<(buffer_t &buffer, const Glib::ustring &data);

私が電話するとき:

buffer << Glib::ustring("hello");

コンパイラは、Glib::ustring による特殊化ではなく、一般的なテンプレート定義を使用します。

ここで何が間違っていますか?

4

2 に答える 2

5
template <typename T> buffer_t &operator<<(buffer_t &buffer, T data);

はプライマリ テンプレートです。スペシャライゼーションはプライマリ テンプレートではありません。コンパイラは、一致する関数の場合にプライマリ テンプレートのみを検索し、選択されたテンプレート関数に特殊化がある場合はこれらを調べ、コンパイラがパラメータと完全に一致する特殊化を検出した場合はそれを使用し、それ以外の場合はプライマリ テンプレートを使用します。

template <> buffer_t &operator<<(buffer_t &buffer, const Glib::ustring &data)

この特殊化は operationbuffer_t << Glib::ustring("s")と正確には一致しませんが、これは正確に一致します

template <> buffer_t &operator<<(buffer_t &buffer, Glib::ustring data)

関数テンプレートの特殊化を使用せず、オーバーロードを使用することをお勧めします。

template <typename T> buffer_t &operator<<(buffer_t &buffer, T data);
buffer_t &operator<<(buffer_t &buffer, const char *data);
buffer_t &operator<<(buffer_t &buffer, const Glib::ustring &data);
于 2012-07-28T19:13:46.287 に答える
5

関数テンプレートがあり、テンプレートの引数推定を実行したいとします。この目的のために、関数呼び出しはテンプレート化された関数引数と照合されますT data。14.8.2.4Pは、テンプレート引数でAあり、実際の引数の型である特殊化の半順序付けに適用されると思います。強調は私のものです):

部分的な順序付けが行われる前に、部分的な順序付けに使用される型に対して特定の変換が実行されます。

Pが参照型の場合、参照される型にP置き換えられます。

が参照型の場合、参照される型に置き換えられます。AA

したがって、引数の型が であるため、A = Glib::ustringこれはプライマリ テンプレートほど特殊化に適していませんconst Glib::ustring &。また、実際の const 参照がある場合でも、部分的な順序付け中に参照が取り除かれます。再び悪い試合に終わります。

これを修正する通常の方法は、プライマリ テンプレートを const 参照にすることです。これは一時オブジェクトにバインドすることもできるため、値引数と「同等」である必要があります。

template <typename T> buffer_t & operator<<(buffer_t & buffer, T const & data);
//                                                             ^^^^^^^^^
于 2012-07-28T18:22:41.997 に答える