enum 型とテンプレート特殊化
追記: テンプレートの特殊化と同時にインスタンス化されていたというだけでした。
仕様のどこに書いてあるのかは調査中以下のように template specialization というのはインスタンス化されたもの、明示的に特殊化されたもの両方を内包する概念のようでした。14.7.4: An instantiated template specialization can be either implicitly instantiated (14.7.1) for a given argument list or be explicitly instantiated (14.7.2). A specialization is a class, function, or class member that is either instantiated or explicitly specialized (14.7.3).
ISO/IEC 14882:1998 (たぶん本物) から引用。
3.9.2.1: enumerations, which comprise a set of named constant values. Each distinct enumeration constitutes a different enumerated type
と、あるんですが...
enum X { A }; template<typename T_> struct foo { struct bar; enum { _ = sizeof(bar) }; }; template<> struct foo<enum X> {}; #ifdef OUCH /* 以下の specialization が、上の enum X より優先される? */ template<> struct foo<int> { struct bar; enum { _ = sizeof(bar) }; }; #endif foo<enum X> _1;
うーん、こういうもんだっけ?
ちなみに、
enum X { A }; enum Y { B }; template<typename T_> struct foo { struct bar; enum { _ = sizeof(bar) }; }; template<> struct foo<enum X> {}; foo<enum X> _1; #ifdef OUCH foo<enum Y> _2; #endif
で、
#include <typeinfo> #include <iostream> enum X { A }; template<typename T_> inline bool is_int(T_ const& val) { return typeid(val) == typeid(int); } int main() { std::cout << is_int(1) << std::endl; // 1 std::cout << is_int(A) << std::endl; // 0 return 0; }
で、
#include <iostream> enum X { A }; template<typename T_> struct foo { static const int value = 0; }; template<> struct foo<enum X> { static const int value = 1; }; template<> struct foo<int> { static const int value = 2; }; int main() { std::cout << foo<enum X>::value << std::endl; // 1 }
ところで、
// 3.9.1.1: char, signed char, and unsigned char are three distinct types. template<typename T_> struct foo { struct bar; enum { _ = sizeof(bar) }; }; template<> struct foo<signed char> {}; foo<signed char> _1; #ifdef OUCH // signed int / int と違って、 // char は signed char とは違う型 (distinct type) foo<char> _2; #endif
これは仕様通り。
// 3.9.1.5: Type wchar_t shall have the same size, signedness, and alignment requirements (3.11) as one of the other integral types, called its underlying type. template<typename T_> struct foo { struct bar; enum { _ = sizeof(bar) }; }; template<> struct foo<signed wchar_t> {}; foo<signed wchar_t> _1; foo<wchar_t> _2; // OK
こちらも仕様通りなんだけど、ちょっと一貫性がないですね。