本C++ Primerには、関数テンプレートのオーバーロードに関する例があります。
// print any type we don't otherwise handle template <typename T> string debug_rep(const T &t) { cout << "debug_rep(T const&)\n"; ostringstream ret; // see § 8.3 (p. 321) ret << t; // uses T's output operator to print a representation of t return ret.str(); // return a copy of the string to which ret is bound } // print pointers as their pointer value, followed by the object to which the pointer points // NB: this function will not work properly with char*; see § 16.3 (p. 698) template <typename T> string debug_rep(T *p) { std::cout << "debug_rep(T*)\n"; ostringstream ret; ret << "pointer: " << p << '\n'; // print the pointer's own value if (p) ret << " " << debug_rep(*p); // print the value to which p points else ret << " null pointer"; // or indicate that the p is null return ret.str(); // return a copy of the string to which ret is bound }
ポインターを指定して debug_rep を呼び出すと、次のようになります。
cout << debug_rep(&s) << endl;
両方の関数が実行可能なインスタンス化を生成します。
debug_rep(const string* &)
T
にバインドされたdebug_rep の最初のバージョンのインスタンス化です。string*
debug_rep(string*)
debug_rep
にT
バインドされた の 2 番目のバージョンのインスタンス化です。string*
の 2 番目のバージョンのインスタンス化は、
debug_rep
この呼び出しと完全に一致します。最初のバージョンのインスタンス化では、プレーン ポインターを へのポインターに変換する必要があります
const
。通常の関数の一致では、2 番目のテンプレートを優先する必要があり、実際にそれが実行されます。
しかし、文字列へのポインターを宣言すると、const
変換は行われず、2 番目のバージョンが常に選択されます。
string const s("hi"); // const
cout << debug_rep(&s) << '\n';
だから私はそれが本の間違いだと思います.バージョンはポインタを取るかどうかを渡すので、バージョンが好ましいconst
と思いT
ます.std::string const*
std::string*
どう思いますか?