Вопрос

Мы с другом обсуждали шаблоны C ++.Он спросил меня, что это должно сделать:

#include <iostream>

template <bool>
struct A {
    A(bool) { std::cout << "bool\n"; }
    A(void*) { std::cout << "void*\n"; }
};

int main() {
    A<true> *d = 0;
    const int b = 2;
    const int c = 1;
    new A< b > (c) > (d);
}

Последняя строка в main содержит два разумных разбора.Является ли 'b' аргументом шаблона или b > (c) аргумент шаблона?

Хотя скомпилировать это и посмотреть, что мы получим, тривиально, нам было интересно, что устраняет двусмысленность?

Это было полезно?

Решение

AFAIK, это было бы скомпилировано как new A<b>(c) > d.Это единственный разумный способ разобрать его, ИМХО.Если синтаксический анализатор не может предположить при обычных обстоятельствах a > end аргумент шаблона, это привело бы к гораздо большей двусмысленности.Если вы хотите, чтобы было по-другому, вам следовало бы написать:

new A<(b > c)>(d);

Другие советы

Как указано Leon & Lee, 14.2 / 3 (C ++ '03) явно определяет это поведение.

C ++ '0x добавляет веселья, применяя аналогичное правило к >>.Основная концепция заключается в том, что при разборе списка шаблонов-аргументов не вложенный >> будут рассматриваться как два различных > > токены, а не оператор правильного сдвига:

template <bool>
struct A {
  A(bool);
  A(void*);
};

template <typename T>
class C
{
public:
  C (int);
};

int main() {
    A<true> *d = 0;
    const int b = 2;
    const int c = 1;
    new C <A< b  >>  (c) > (d); // #1
    new C <A< b > >  (c) > (d); // #2
}

'#1' и '#2' эквивалентны в приведенном выше примере.

Это, конечно, устраняет проблему с добавлением пробелов во вложенных специализациях:

C<A<false>> c;  // Parse error in C++ '98, '03 due to "right shift operator"

Стандарт C ++ определяет, что если для имени шаблона, за которым следует <, тот самый < всегда является началом списка аргументов шаблона и первым не вложенным > берется в конце списка аргументов шаблона.

Если вы предполагали, что результат > operator является аргументом шаблона, тогда вам нужно будет заключить выражение в круглые скобки.Вам не нужны круглые скобки, если аргумент был частью static_cast<> или другое шаблонное выражение.

Жадность лексера, вероятно, является определяющим фактором в отсутствии круглых скобок, делающих его явным.Я бы предположил, что лексер не жадный.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top