несколько вложенных зависимых имен - куда вставить ключевое слово typename?

Этот вопрос был вызван другим вопросом . Пытаясь ответить на этот вопрос, я понял, что у меня самого много вопросов. Итак ... Примите во внимание следующее:

struct S1
{
    enum { value = 42 };
};

template  struct S2
{
    typedef S1 Type;
};

template  struct S3
{
    typedef S2 Type; 
};

template  struct S4
{
    typedef typename T::Type::Type Type;  //(1)//legal?
    enum {value = T::Type::Type::value }; //(2)//legal?
};

int main()
{
    S4 > > >::value;
}

Это успешно компилируется с MSVC9.0 и Online Comeau. Однако меня беспокоит то, что я не понимаю, к чему относится typename в (1) и почему нам не нужно typename в (2).

] Я пробовал эти 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};  

Хороший стиль оставлен в стороне, должны ли мы синтаксически использовать упомянутый мной обходной путь?

Остальное - просто интересный пример. Не надо читать. Не имеет отношения к вопросу.

Обратите внимание, что, хотя MSVC принимает оригинальный странный синтаксис без нескольких typename s (я имею в виду (1) и (2)), это приводит к странному поведению, как в упомянутый вопрос. Думаю, я представлю этот пример в краткой форме и здесь:

struct Good
{
    enum {value = 1}; 
};
struct Bad
{
    enum {value = -1};  
};

template 
struct ArraySize
{
    typedef Bad Type;
};
template 
struct ArraySize
{
    typedef Good Type;
};

template 
struct Boom
{
    char arr[ArraySize::Type::value]; //error, negative subscript, even without any instantiation
};

int main()
{
    Boom b; //with or without this line, compilation fails.
}

Это не компилируется. Обходной путь, о котором я упоминал, решает проблему, но я уверен, что проблема здесь в моем первоначальном вопросе - отсутствует имя типа, но вы действительно не знаете, куда его вставить. Заранее большое спасибо.

10
задан Community 23 May 2017 в 12:33
поделиться