2017-01-25 1 views
43

Я очень хорошо знаю, почему нужно использовать typename для зависимых типов, так как компилятор может не иметь возможности устранить неоднозначность между типом и объявлением переменной, когда он видит что-то вроде T::type, см., Например, this answer для отличного объяснения. TL; DR: в выражении типа T::type * x; компилятор не может «знать», является ли T::type типом или, возможно, переменной, объявленной в определенной специализации для T.Почему все еще необходимо устранить двунаправленный тип зависимого типа с именем типа в RHS использующего оператора?

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

using type = T::type; 

нет ничего неоднозначного. IMO, T::typeвсегда следует анализировать как тип, так как он является частью RHS инструкции using. Тем не менее, мы по-прежнему необходимо использовать typename здесь (по крайней мере, в соответствии с НКУ и лязгом),

using type = typename T::type; 

Live on Coliru, gcc Live on Coliru, clang

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

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

+3

Для downvoters: Я не задаю вопросы ради получения некоторых баллов. Если вы думаете, что вопрос - это дерьмо, или ответ тривиален, по крайней мере, дайте мне знать. Я очень хотел бы, чтобы современный C++ упрощался, и получение более чистого синтаксиса (imo) стоит. – vsoftco

+0

Это один из случаев «никто никогда не предлагал». Я не могу думать о техническом аргументе против него. – Columbo

+0

@Columbo Вот почему я задал вопрос, это комментарий к комментарию Брайана для [его ответа] (http: // stackoverflow.com/a/41841216/3093378) на [этот вопрос] (http://stackoverflow.com/q/41841195/3093378). – vsoftco

ответ

0

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

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

+0

Я помню, что в пункте 9 современного C++ есть ваш вопрос, чтобы выбрать использование вместо typedef. Может быть, на этот раз vc больше compianto чем clang? – alangab

+1

Дело в том, что вы * уже * сказали компилятору, что тип 'T :: type' является типом, потому что вы не можете поместить не-тип в RHS объявления' using'. Зачем вам нужно снова указывать * с помощью 'typename'? В других местах это необходимо для устранения неоднозначности, но не здесь. –

+0

Вы * можете * поставить там не-тип, и он выдаст диагностику. Это сделает язык нерегулярным, если он изменит это и может иметь много непредвиденных последствий, что приводит к закрытию путей эволюции. В настоящее время 'T :: a' (для шаблона класса' T') всегда является значением, за которым предшествует 'typename', а' using' всегда сообщает об ошибке при использовании со значением. Это регулярное правило, и поэтому легко объяснить, реализовать и спланировать эволюцию языка. – codeshot

2

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

  1. Это можно рассматривать как сделать язык менее регулярным (как codeshot said), но новая идея состоит в том, что неоднозначности typename станет достаточно редко, чтобы иметь почти последовательности в других направление. (Как has been said, был уже исключительный случай в виде имен базового класса.)
  2. Он мог исключить возможные расширения (как T.C. reported), но расширения могут иметь свои собственные значения, а не обременять общий случай.

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

Смежные вопросы