Я думаю, что стоит рассказать вам о подобной проблеме, которая также вызывает проблемы:
struct foo { };
struct bar { bar(foo f); };
int main() {
// does *not* create a bar object initialized by a default constructed
// foo object.
bar b(foo());
}
Что на самом деле представляет собой функция b, которая возвращает bar
и принимает в качестве первого аргумента указатель на функцию, которая возвращает foo без аргументов. Это так же, как:
bar b(foo(*)());
Если вы хотите создать объект bar, инициализированный с помощью созданного по умолчанию foo, поставьте вокруг аргумента скобки. Это делает его больше не похожим на объявление функции, и компилятор интерпретирует его так, как вы хотите:
bar b((foo()));
Есть также неочевидные случаи, когда ошибка компилятора должна возникать. GCC понимает это неправильно, но Comeau понимает это снова. Рассмотрим следующий фрагмент
struct foo {
static bool const value = false;
};
int main() {
int v(int(foo::value));
}
Вы, вероятно, ожидаете, что это принимает статическую константу и приводит ее к int
, инициализируя переменную v
равной 0
? Нет, в соответствии со Стандартом это не будет, потому что инициализатор может быть интерпретирован как объявление, в соответствии с чистым синтаксическим анализом, как показано ниже
struct foo {
static int value;
};
// valid, parentheses are redundant! Defines `foo::value`.
int (foo::value);
Всякий раз, когда инициализатор можно интерпретировать как объявление, в такой ситуации вся декларация будет объявлять функцию. Итак, строка в main
объявляет функцию, подобную следующей, опуская лишние и бессмысленные скобки
int v(int foo::value);
И это приведет к ошибке компилятора при разборе объявления функции, поскольку имя параметра функции может быть не квалифицированным.