この質問は、この他の質問に触発されました。その質問に答えようとしているうちに、私は自分自身にたくさんの質問があることを理解しました。だから...次のことを考慮してください:
struct S1
{
enum { value = 42 };
};
template <class T> struct S2
{
typedef S1 Type;
};
template <class T> struct S3
{
typedef S2<T> Type;
};
template <class T> struct S4
{
typedef typename T::Type::Type Type; //(1)//legal?
enum {value = T::Type::Type::value }; //(2)//legal?
};
int main()
{
S4<S3<S2<S2<S1> > > >::value;
}
これは、MSVC9.0およびOnlineComeauで正常にコンパイルされます。しかし、気になるのはtypename
、(1)で何を言っているのか、(2)でなぜ必要ないのかわからないことですtypename
。
私はこれらの2つの構文(構文?)を試しましたが、どちらもMSVCでは失敗するはずです。
typedef typename T::typename Type::Type Type;
enum {value = typename T::typename Type::Type::value };
と
typedef typename (typename T::Type)::Type Type;
enum {value = (typename (typename T::Type)::Type)::value };
もちろん、回避策はtypedef
次のように連続してを使用することです。
typedef typename T::Type T1;
typedef typename T1::Type Type;
enum { value = Type::value};
良いスタイルは脇に置いておきますが、構文的には、前述の回避策を使用する必要がありますか?
残りは興味深い例です。読む必要はありません。質問にはそれほど関係ありません。
typename
MSVCは複数のs(つまり(1)と(2))のない元の奇妙な構文を受け入れますが、前述の質問のように奇妙な動作を引き起こすことに注意してください。ここでもその例を簡潔な形で提示すると思います。
struct Good
{
enum {value = 1};
};
struct Bad
{
enum {value = -1};
};
template <class T1, class T2>
struct ArraySize
{
typedef Bad Type;
};
template <class T>
struct ArraySize<T, T>
{
typedef Good Type;
};
template <class T>
struct Boom
{
char arr[ArraySize<T, Good>::Type::value]; //error, negative subscript, even without any instantiation
};
int main()
{
Boom<Good> b; //with or without this line, compilation fails.
}
これはコンパイルされません。私が言及した回避策は問題を解決しますが、ここでの問題は私の最初の質問であると確信しています-タイプ名がありませんが、どこに貼り付けるかは本当にわかりません。よろしくお願いします。