2

I need to create a dynamic library:

mylib.h

class FriendClass;

namespace my_namespace
{

class MyLib
{
    friend class FriendClass;

public:
    MyLib();

    /* public functions */

private:
    void function_for_friend_class();
};

} // namespace my_namespace

And use it here

friend_function.h

class FriendClass
{
public:
    void some_function()
    {
        MyLib* my_lib = get_my_lib_somehow();
        my_lib->function_for_friend_class();
    }
};

With gcc3.4 it compiles, but gcc4.9 complains that function_for_friend_class is private. What am I doing wrong?

user1289
  • 1,251
  • 2
  • 13
  • 25
  • 2
    Try either `friend class ::FriendClass;`. or `friend FriendClass;` – n. m. could be an AI Jul 05 '16 at 07:16
  • But isn't it looking into global namespace, when it'll not find in current one? – user1289 Jul 05 '16 at 07:19
  • 1
    `friend class xxx` declares a new class if possible, `friend xxx` looks for an existing class. – n. m. could be an AI Jul 05 '16 at 07:25
  • gcc34 - "a class-key must be used when declaring a friend", only `class ::FriendClass` works in both versions. – user1289 Jul 05 '16 at 07:40
  • 3.4 is old and may not be fully conforming. – n. m. could be an AI Jul 05 '16 at 07:42
  • @n.m. It's weird to me. For [friend elaborated-class-name;](http://en.cppreference.com/w/cpp/language/friend), why unqualified name lookup doesn't find the name in global scope for [Elaborated type specifier](http://en.cppreference.com/w/cpp/language/elaborated_type_specifier)? – songyuanyao Jul 05 '16 at 07:52
  • @songyuanyao hmm it looks like I was wrong, `friend class xxx declares a new class if possible` is incorrect, the program seems OK and gcc 4.9 is wrong. – n. m. could be an AI Jul 05 '16 at 08:12
  • @n.m. if that's the case, add clang 3.8 to the list. `friend FriendClass;` properly resolves; `friend class FriendClass;` does not, when setup as the OP describes. See it [fail to compile here](http://coliru.stacked-crooked.com/a/3900ca1ad9a2fddc), and [succeed here](http://coliru.stacked-crooked.com/a/c43db5007f50655c) – WhozCraig Jul 05 '16 at 08:13
  • @n.m. But Clang failed too...Clang and GCC are both wrong? Maybe we still missed something.. – songyuanyao Jul 05 '16 at 08:15
  • @songyuanyao No wait, either I misunderstand something in the standard or gcc, clang and icc are all wrong, which would be weird. Microsoft compilers accept this. – n. m. could be an AI Jul 05 '16 at 08:26
  • @n.m. Maybe VS is correct? Which is the most weird to me.. – songyuanyao Jul 05 '16 at 08:30
  • 1
    @songyuanyao OK I think I found it: *If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace" (7.3.1.2/3). So the lookup should not find the global FriendClass, and thus the friend declaration introduces a new FriendClass in MyLib namespace. I was right and the usual suspect is wrong after all. – n. m. could be an AI Jul 05 '16 at 08:43
  • @n.m. Awesome! This is the answer. (You might put it as the answer, with the workaround together.) – songyuanyao Jul 05 '16 at 08:51

1 Answers1

0

Use friend class ::FriendClass; By doing this, you tell the compiler to look in the global namespace of the definition of class FriendClass, not in the current namespace.

Also use:

my_namespace::MyLib* my_lib = get_my_lib_somehow();
Mattia F.
  • 1,720
  • 11
  • 21
  • Because by writing "friend class FriendClass;" you tell the compiler to look in the current namespace only, non in the global one. – Mattia F. Jul 05 '16 at 08:28
  • [Unqualified name lookup](http://en.cppreference.com/w/cpp/language/unqualified_lookup#Namespace_scope) should find the name if you don't specify the scope explicitly. The problem is why it doesn't work here. – songyuanyao Jul 05 '16 at 08:32