Кто-то на днях спросил, почему что-то компилируется с clang, но не с gcc. Я интуитивно понимал, что происходит, и мог помочь человеку, но это заставило меня задуматься - согласно стандарту, какой компилятор был правильным? Вот упрощенная версия кода:

#include <iostream>
#include <string>

class foo
{
public:
    foo(const std::string& x):
        name(x)
    { }
    foo& operator()(const std::string& x)
    {
        std::cout << name << ": " << x << std::endl;
        return (*this);
    }
    std::string name;
};

int main()
{
    std::string x = "foo";
    foo(x)("bar")("baz");
    return 0;
}

Это нормально компилируется с clang ++, но g ++ дает следующую ошибку:

runme.cpp: In function ‘int main()’:
runme.cpp:21:11: error: conflicting declaration ‘foo x’
    foo(x)("bar")("baz");
        ^
runme.cpp:20:17: error: ‘x’ has a previous declaration as ‘std::string x’
    std::string x = "foo";

Если я добавлю пару скобок в строку 21, g ++ будет счастлив:

(foo(x))("bar")("baz");

Другими словами, g ++ интерпретирует эту строку как:

foo x ("bar")("baz");

Мне кажется, это ошибка в g ++, но опять же, я хотел спросить стандартных экспертов, какой компилятор ошибся?

PS: gcc-4.8.3, clang-3.5.1

25
Innocent Bystander 2 Фев 2015 в 20:22

1 ответ

Если убрать строчку

std::string x = "foo";

То g ++ жалуется на:

foo(x)("bar")("baz");

С синтаксической ошибкой:

foo.cc:20:18: error: expected ',' or ';' before '(' token
     foo(x)("bar")("baz");

Я не понимаю, как foo (x)("bar")("baz"); может быть допустимым объявлением, и, очевидно, g ++ тоже не может. Строка foo x("bar")("baz"); отклоняется с той же ошибкой.

«Разрешение двусмысленности», упомянутое в сообщении Шафика, срабатывает только тогда, когда выражение-выражение синтаксически неотличимо от объявления. Однако в этом случае это недопустимый синтаксис объявления, поэтому нет двусмысленности, это должен быть оператор-выражение.

G ++ не может обработать строку как выражение-оператор, поэтому это ошибка g ++.

Это очень похоже на эту ошибку g ++. недавно обсуждался на SO; кажется, что g ++ слишком рано решает при обработке, что строка должна быть объявлением.

5
Community 23 Май 2017 в 12:33