Подтвердить что ты не робот

Почему все еще необходимо устранить двунаправленный тип зависимого типа с именем типа в RHS используемого оператора?

Я очень хорошо знаю, почему нужно использовать typename для зависимых типов, поскольку компилятор не может устранить неоднозначность между объявлением типа и переменной, когда он видит что-то вроде T::type, см., например, этот ответ для отличного объяснения. TL; DR: в выражении типа T::type * x; компилятор не может "знать", является ли тип T::type типом или, возможно, переменной, объявленной в определенной специализации для T.

Однако, что-то вроде

using type = T::type;

нет ничего двусмысленного. IMO, T::type всегда следует анализировать как тип, как часть RHS оператора using. Однако нам все еще нужно использовать typename здесь (по крайней мере, согласно gcc и clang),

using type = typename T::type;

Live on Coliru, gcc Live on Coliru, clang

Visual С++ кажется, принимает код без typename, однако у меня нет слишком большой веры в то, что компилятор является полностью стандартным (на самом деле у него много нестандартных расширений, например, привязка значений r к неконстантным ссылкам).

Вопрос: Есть ли причина, по которой это не является исключением из правила typename в С++ 11 и более поздних версиях?

4b9b3361

Ответ 1

Нет жесткой причины. Как сказал ralismark, в этом году обсуждался документ (для С++ 20, а не 17!). Есть проблемы, но также контрапункты:

  • Можно считать, что язык менее регулярный (как codehot сказал), но новая идея заключается в том, что устранение неполадок typename станет достаточно редким, чтобы почти согласованность в другом направлении. (Как говорилось , уже существовал исключительный случай в виде имен базового класса.)
  • Он может отказаться от возможных расширений (как T.C. сообщил), но расширения могут иметь свою собственную неоднозначность, а не обременять общий случай.

У бумаги есть сильная поддержка, и новые правила, вероятно, появятся в рабочем проекте через несколько месяцев.

Ответ 2

Тип аргумента шаблона T не имеет и не может неявно содержать с собой его внутренние компоненты. таким образом, тип T:: является принципиально новым типом, когда компилятор просматривает необоснованный шаблон, поэтому необходимо объявить новое имя типа "T:: type".

К сожалению, я думаю, что этот вопрос останется с нами до тех пор, пока стандарт не включит полноценные концепции.