non-template friend definition inside template error


I wanna define a friend function inside the template not outside but the linker cannot get it :
1
2
3
4
5
6
7
void func();
template<typename T>
class test {
	friend void func() {
		cout << "worked" << endl;
	}
};


when I call this function on an ordinary class it works but with templates, it gives me this
error : LNK2019 unresolved external symbol "void __cdecl func(void)" (? func@@YAXXZ) referenced in function _main
in addition, if I defined the function outside the template it works!!

1
2
3
4
5
6
7
void func() {
	cout << "worked" << endl;
}
template<typename T>
class test {
	friend void func();
};


what is wrong in my code ?
Last edited on
func() is private within test<T>, so it's not visible to main().

You'll need to separate the friend declaration from the definition of the function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
  
template <typename T>
class test
{
public:
    friend void func();
    void func()
    {
        std::cout << "yay!\n";
    }
};

int main()
{
    test<int>().func();
    test<double>().func();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

class Test {
    void memberMethod() { /* do nothing */ }
    friend void notMemberFunction() { /* do nothing */ }
    friend void notMemberDefinedOutside(); // prototype only
};

void notMemberFunction() {} // Error! This is not an overloading, this is
                            // a re-definition.
                            // notMemberFunction() already defined at line 5

void notMemberDefinedOutside() {}   // Fine. This is not a redefinition, since
                                    // so far notMemberDefinedOutside()
                                    // has not been defined, but only declared.

void memberMethod() {}  // Ok. Despite its name, this is *not*
                        // Test::memberMethod()

int main()
{
    return 0;
}

Last edited on
Sorry, AhmedEl3agamy, perhaps I didn’t answer your question.
I think the problem is connected with the nature of friendship and templates.

http://en.cppreference.com/w/cpp/language/friend
2) (only allowed in non-local class definitions) Defines a non-member function, and makes it a friend of this class at the same time. Such non-member function is always inline.


http://en.cppreference.com/w/cpp/language/class_template
A class template by itself is not a type, or an object, or any other entity. No code is generated from a source file that contains only template definitions. In order for any code to appear, a template must be instantiated: the template arguments must be provided so that the compiler can generate an actual class (or function, from a function template).


So, in the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

void func() { std::cout << "func() outside Test\n"; }

template<typename T>
class Test {
    friend void func() { std::cout << "func() friend of Test\n"; }
};

void waitForEnter();

int main()
{
    func(); // The only 'existing' func() is the one outside the template
    waitForEnter();
    return 0;
}

void waitForEnter()
{
    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

I think the problem is the template class Test simply doen’t exist: no code is generated for it. So there can't be any inline function.
But here, it comes to life (and gives redefinition error):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

void func() { std::cout << "func() outside Test\n"; }

template<typename T>
class Test {
    friend void func() { std::cout << "func() friend of Test\n"; }
};

void waitForEnter();

int main()
{
    func(); // The only 'existing' func() is the one outside the template
    Test<int>().func(); // redefinition of func()
    waitForEnter();
    return 0;
}

void waitForEnter()
{
    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Compiler errors:
In instantiation of 'class Test<int>':
15:15:   required from here
7:17: error: redefinition of 'void func()'
     friend void func() { std::cout << "func() friend of Test\n"; }
                 ^~~~
3:6: note: 'void func()' previously defined here
 void func() { std::cout << "func() outside Test\n"; }
      ^~~~
: In function 'int main()':
15:17: error: 'class Test<int>' has no member named 'func'
     Test<int>().func(); // redefinition of func()
                 ^~~~

Topic archived. No new replies allowed.