自分用覚え書き:テンプレートと文字列リテラルの罠のようなもの
C++ Templates: The Complete Guideの57ページにこんなコードがあった。
//--------------------------------------------------------------------------- #pragma hdrstop #include <tchar.h> #include <string> //--------------------------------------------------------------------------- #pragma argsused // note: reference parameters template <typename T> inline T const& max (T const& a, T const& b) { return a < b ? b : a; } int _tmain(int argc, _TCHAR* argv[]) { std::string s; ::max("apple","peach"); // OK: same type ::max("apple","tomato"); // ERROR: different types ::max("apple",s); // ERROR: different types return 0; }
ぶっちゃけた話、2番目のmaxが何故エラーになるかよく判らなかったおいら。エラーメッセージ*1からすると、両方とも"const char *"じゃないかと。
C++は実行時型情報を取得できるので、こんなコードで「正体」を探ってみる。
//--------------------------------------------------------------------------- #pragma hdrstop #include <tchar.h> #include <typeinfo> #include <iostream> //--------------------------------------------------------------------------- #pragma argsused int _tmain(int argc, _TCHAR* argv[]) { std::cout << "typename \"apple\" is " << typeid("apple").name() << std::endl; std::cout << "typename \"peach\" is " << typeid("peach").name() << std::endl; std::cout << "typename \"tomato\" is " << typeid("tomato").name() << std::endl; return 0; }
typeid演算子は実行時型情報であるtype_infoクラスを返す演算子。type_infoクラスのnameメソッドでその型名を取得する。
D:\home\A7M\BCBTEST\template_test1>bcc32 File1.cpp CodeGear C++ 6.10 for Win32 Copyright (c) 1993-2008 CodeGear File1.cpp: Turbo Incremental Link 5.95 Copyright (c) 1997-2008 CodeGear D:\home\A7M\BCBTEST\template_test1>File1 typename "apple" is char[6] typename "peach" is char[6] typename "tomato" is char[7]
つまり、最初のmaxの呼び出しは、char[6]のconst参照とchar[6]のconst参照を渡しているので、同一型と見なされ、2番目のmaxはchar[6]のconst参照とchar[7]のconst参照を渡していたから、違う型と見なされ、エラーになると。エラーメッセージだけを見るとハマる例かも。(おいらだけかもしれないけど・・・。
他にハマる例として、STLの
std::make_pair("key", "value")
が挙げられていたので、罠と言えば罠かも。