аргумент шаблонного класса по умолчанию путает g ++?

Здесь:

testdir = "/volumes/toshiba"
for folder in testdir:

Вы определяете строку (последовательность символов), а затем повторяете ее. Эта последовательность символов. И, конечно, когда вы печатаете последовательность символов, что еще должно быть напечатано, кроме последовательности символов ?!

Вместо этого вы хотите передать эту строку команде, подобной os.listdir(), которая будет возвращать список объектов типа «путь», представляющих фактическое содержимое назначенной записи файловой системы.

9
задан andreas buykx 12 May 2009 в 07:52
поделиться

4 ответа

Я не уверен, что это ошибка в g ++ (начиная с версии 4.2.4). Теперь код переходит в g ​​++ 4.4 (см. ОБНОВЛЕНИЕ ниже). Чтобы этот код компилировался для других версий компиляторов, вы можете добавить набор круглых скобок вокруг аргумента по умолчанию:

template<typename A, typename B>
class Foo { };

struct Bar {
  void method ( Foo<int,int> const& stuff = ( Foo<int,int>() ) );
};

ИМО, эти круглые скобки необходимы, поскольку существует дополнительное требование, чтобы аргумент по умолчанию мог ссылаться на член class, который может быть объявлен позже в теле класса:

struct Bar {
  void method ( int i = j);  // 'j' not declared yet
  static const int j = 0;
};

Приведенный выше код является допустимым, и когда объявление для 'метода' анализируется, член 'j' еще не был замечен. Поэтому компилятор может анализировать аргумент по умолчанию только с использованием синтаксиса и только проверки (т. Е. Соответствия скобкам и запятым). Когда g ++ анализирует исходное объявление, на самом деле он видит следующее:

void method ( Foo<int,int> const& stuff = Foo<int // Arg 1 with dflt.
              , int>() );                         // Arg 2 - syntax error

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

В следующем случае показан пример, когда g ++ успешно работает, но Comeau по-прежнему генерирует синтаксическую ошибку:

template<int J, int K>
class Foo { };

struct Bar {
  void method ( Foo<0, 0> const & i = ( Foo<j, k> () ) );
  static const int j = 0;
  static const int k = 0;
};

EDIT:

В ответ на комментарий: «Вы могли бы также иметь там вызов функции с несколькими аргументами», Причина, по которой это не вызывает проблемы, заключается в том, что запятые внутри вызова функции заключены в круглые скобки:

int foo (int, int, int);
struct Bar {
  void method ( int j =
                    foo (0, 0, 0) ); // Comma's here are inside ( )
};

Следовательно, можно проанализировать это, используя только синтаксис выражения. В C ++ все символы '(' должны совпадать с ')', поэтому их легко проанализировать. Причина проблемы здесь в том, что '<' не нужно сопоставлять, поскольку он перегружен в C ++ и поэтому может быть оператором «меньше» или началом списка аргументов шаблона. В следующем примере показано, где «<» используется в аргументе по умолчанию и подразумевает оператор «меньше чем»:

template<int I, int J>
class Foo { };

struct Bar {
  template <typename T> struct Y { };

  void method ( ::Foo<0,0> const& stuff = Foo<10 , Y < int >  = Y<int>() );

  struct X {
    ::Foo<0, 0> operator< (int);
  };

  static X Foo;
};

Вышеупомянутое «Foo <10» является вызовом «operator <», определенным в «X», а не началом список аргументов шаблона. Опять же, Comeau генерирует синтаксические ошибки в приведенном выше коде, и g ++ (включая 3.2.3) анализирует это правильно.

FYI, соответствующие ссылки - это примечание в 8.3.6 / 5:

[Примечание: в объявлениях функций-членов просматриваются имена в выражениях аргументов по умолчанию вверх, как описано в 3.4.1 ...

, а затем в 3.4.1 / 8

Имя, используемое в определении функции-члена (9.3) класса X после декларатора функции29) должен быть объявлен одним из следующих способов:

...

- должен быть членом класса X или быть членом базового класса X (10.2), или

Этот пункт здесь является часть, которая заставляет компилятор «откладывать» поиск значения аргумента по умолчанию до тех пор, пока не будут объявлены все члены класса.

Как указано в «Русском языке», g ++ 4.4 теперь является способен разобрать все эти примеры. Однако до тех пор, пока DR не будет рассмотрен комитетом по стандартам C ++, я еще не готов называть это «ошибкой». Я считаю, что для обеспечения переносимости на другие компиляторы / инструменты (и, возможно, даже в будущие версии g ++) потребуются дополнительные круглые скобки.

По моему опыту, стандарт C ++ не требует, чтобы все поставщики компиляторов использовали одну и ту же технологию синтаксического анализа, и они также не могут ожидать, что все технологии будут одинаково мощными. В результате требования к синтаксическому анализу обычно не требуют, чтобы поставщики совершали сверхчеловеческие подвиги. Чтобы проиллюстрировать это, рассмотрим следующие два примера:

typedef T::TYPE TYPE;
T::TYPE t;

Если 'T' является зависимым, то с учетом каждого контекста 'TYPE' должен быть именем типа, однако стандарт по-прежнему требует typename ключевое слово. Эти примеры недвусмысленны и могут означать только одно, однако в стандарте (чтобы разрешить все технологии синтаксического анализа) по-прежнему требуется ключевое слово typename .

Это Возможно, что DR может быть адресован таким образом, что компилятор, который не может проанализировать эти примеры, по-прежнему будет «соответствовать стандарту» до тех пор, пока дополнительные скобки позволяют коду анализировать.

12
ответ дан 4 December 2019 в 13:05
поделиться

Похоже на ошибку компилятора. Я попробовал его на компиляторе IBM xlC V7.0 (который, как я обнаружил, более соответствует стандартам, чем gcc), и он компилируется нормально.

2
ответ дан 4 December 2019 в 13:05
поделиться

Это известная ошибка в gcc. Это было исправлено в gcc-4.4, который отлично компилирует исходный код.

4
ответ дан 4 December 2019 в 13:05
поделиться
template <bool> class A {};
typedef A<static_cast<bool>(1>0)> B;//buggy
int main() { B b; }
-2
ответ дан 4 December 2019 в 13:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: