На самом деле все довольно просто: если видна открытая скобка шаблона, >
закрывает ее, даже если в противном случае >
станет частью оператора >>
.(Это не относится к >
символам, которые являются частью других токенов, например >=
.) Это изменение синтаксиса C ++ было частью C ++ 11.
Открытая скобка шаблона не являетсявидимый, если >
находится внутри вложенного в скобки синтаксиса.Таким образом, >>
в T<sizeof a[x >> 1]>
и T<(x >> 1)>
являются операторами сдвига вправо, в то время как T<x >> 1>
, вероятно, не выполняет синтаксический анализ, как ожидалось.
Обе стратегии реализации могут работать в зависимости от того, где вы хотитепоставить сложность.Если лексер никогда не генерирует токен >>
;Парсер может проверить, что токены >
в expr '>' '>' expr
смежны, посмотрев на их исходные местоположения.Будет конфликт сдвига-уменьшения, который должен быть решен в пользу сокращения списка параметров шаблона.Это работает, потому что случается так, что нет никакой двусмысленности, созданной разделением >>
на два токена, но это не общее правило: a + ++ b
отличается от a ++ + b
;если бы лексер генерировал только +
токены, это было бы неоднозначно.
Не так уж сложно решить проблему с помощью хекса лексера, если вы готовы к тому, чтобы глубина скобок в лексере отслеживалась.Это означает, что лексер должен знать, является ли <
скобкой шаблона или оператором сравнения, но вполне возможно, что он это делает.
Это более интересный вопрос (по крайней мере, imho): как<
распознается как скобка шаблона, а не как оператор меньше чем?Здесь действительно есть семантическая обратная связь: это скобка шаблона, если она следует за именем, которое обозначает шаблон.
Это не простое определение.Имя может быть членом класса или объединения и даже членом специализации шаблонного класса или объединения.В последнем случае может потребоваться вычислить значения константных выражений во время компиляции, а затем выполнить шаблонное вычитание, чтобы определить, какое имя обозначает.