Ошибка компилятора при объявлении функции-друга с типом возвращаемого значения typedef - PullRequest
2 голосов
/ 09 января 2020

Минимальный пример:

#include <cstdint>

std::int32_t someFunc();

namespace foo
{
class FooClass
{
private:
    void bar(){}
    friend std::int32_t ::someFunc();
};
}

std::int32_t someFunc()
{
    foo::FooClass c;
    c.bar();
    return 0;
}


int main(int argc, const char * argv[])
{
    return someFunc();
}

Создание этого кода приводит к следующей ошибке: pathTo / fooClass.hpp: 8: 17: 'int32_t' (он же 'int') не является классом, пространством имен, или перечисление

Другая интересующая информация:

  • Если не удалось проанализировать объявление друга, компилятор также жалуется, что bar () является закрытой, что ожидается.
  • Если вы измените объявление друга на "friend int :: someFun c ();" пример кода будет скомпилирован без каких-либо других изменений.
  • объявив "typedef int myInt;" и использование myInt в качестве типа возврата в объявлении друга также не скомпилируется с той же ошибкой.
  • Похоже, не указывается платформа c: происходит как с MacOS, так и с Android toolchains

Таким образом, это связано с тем, что тип возвращаемого значения в Объявление друга - это typedef, но я не понимаю, почему это будет проблемой. Может кто-нибудь объяснить, почему приведенный выше код не компилируется?

РЕДАКТИРОВАТЬ: Как это часто бывает, я слишком поздно понял, в чем проблема. Компилятор анализирует этот код, как если бы someFun c был членом std :: int32_t, который действительно не является допустимым синтаксисом. Итак, мой новый вопрос: как сделать объявление друга в такой ситуации, где :: ДОЛЖНО предшествовать someFun c в объявлении друга, чтобы разрешить правильно?

1 Ответ

1 голос
/ 09 января 2020

Не уверен, что это ошибка или нет. Но когда дело доходит до двусмысленности в декларациях, решением обычно является правильное использование скобок. Вы можете изменить объявление своего друга следующим образом

friend std::int32_t (::someFunc)();

, что заставит оператор разрешения области видимости корректно связываться с идентификатором объявления вместо типа.

Живой пример

Части декларатора (даже просто идентификатор) в общем случае можно заключить в скобки, а иногда они должны быть для того, чтобы получить правильное значение. Например, старая разница между функцией, возвращающей указатель и указатель на функцию

int *foo();
int (*bar)();
...