Minimal example:
#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();
}
Building this code results in the following error: pathTo/fooClass.hpp:8:17: 'int32_t' (aka 'int') is not a class, namespace, or enumeration
Other info of interest:
So this appears to be related to the fact that the return type in the friend declaration is a typedef, but I don't understand why that would be a problem. Can some one explain why the above code does not compile?
EDIT: As is often the case, I realized moments too late what the problem is. The compiler is parsing this code as if someFunc were a member of std::int32_t which is indeed not valid syntax. So my new question is, how would one do a friend declaration in a situation like this where :: MUST precede someFunc in the friend declaration to resolve properly?
Not sure if it's a bug or not. But when it comes to ambiguity in declarations, the solution is usually the correct use of parentheses. You can amend your friend declaration as follows
friend std::int32_t (::someFunc)();
Which will force the scope resolution operator to bind correctly to the declarator id instead of the type.
Parts of the declarator (even just the id) can be parenthesized in general, and sometimes they need to be in order to get the correct meaning. For instance, the age old difference between a function returning a pointer and a pointer to a function
int *foo();
int (*bar)();