Неопределенность шаблона C ++ - PullRequest
6 голосов
/ 09 сентября 2008

Мы с другом обсуждали шаблоны 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) аргументом шаблона?

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

Ответы [ 4 ]

6 голосов
/ 16 сентября 2008

Как заявлено Леоном и Ли, 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"
5 голосов
/ 09 сентября 2008

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

new A<(b > c)>(d);
3 голосов
/ 10 сентября 2008

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

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

0 голосов
/ 09 сентября 2008

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

...