Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
234 views
in Technique[技术] by (71.8m points)

c++ - How do I call a friend template function defined inside a class?

I got this example from my book, but I have no idea how to actually call the ticket function. This is the code:

#include <iostream>
    class Manager { 
    public:
        template<typename T> 
            friend int ticket() { 
                return ++Manager::counter; 
            } 
        static int counter; 
    }; 
   
int main()
{
    Manager m;
    std::cout << "ticket: " << ticket<int>() << std::endl;
}

I get the "candidate function(s) not accessible" error message.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A few points will help you figure out what's going on here:

I) Friend function definitions within classes can only be found by Argument dependent lookup when called from outside the class definition.

II) Function templates that are supplied explicit template arguments do not undergo ADL unless the compiler is given some explicit help in identifying the call as a function call.

III) Argument dependent lookup (ADL) only works for user defined types.

A few examples will better illustrate each of the above points:

//------------------------
struct S 
{
  friend int f(int) { return 0; }  // 1
  friend int f(S) { return 0; }    // 2

};

S s;
int i = f(3); // error - ADL does not work for ints, (III) 
int j = f(s); // ok - ADL works for UDTs and helps find friend function - calls 2 (III)

// so how do we call function 1? If the compiler won't find the name via ADL
// declare the function in the namespace scope (since that is where the friend function
// gets injected)

int f(int);  // This function declaration refers to the same function as #1
int k = f(3); // ok - but not because of ADL 

// ok now lets add some friend templates and make this interesting
struct S 
{
  friend int f(int) { return 0; }  // 1
  friend int f(S) { return 0; }    // 2
  template<class T> friend int g(int) { return 0; } // 3
  template<class T> friend int g(S) { return 0; } // 4
  template<class T> friend int g() { return 0; } // 5
};
S s;
int k = g(5); // error - no ADL (III)
int l = g(s); // ok - ADL - calls 4
int m = g<int>(s); // should call 4 - but no ADL (point II above)

// ok so point II above says we have to give the compiler some help here
// We have to tell the compiler that g<int> identifies a function
// The way to do that is to add a visible dummy template function declaration

template<class /*Dummy*/, class /*TriggerADL*/> void g(); 

int m = g<int>(s); // ok - compiler recognizes fun call, ADL triggered - calls 4
int n = g<int>(3); // still not ok - no ADL for ints

// so how do we call either function 3 or 5 since we cannot rely on ADL?
// Remember friend functions are injected into the outer namespace
// so lets just declare the functions in the outer namespace (as we did above)
// both these declarations of g below refer to their counterparts defined in S
template<class T> int g(int);
template<class T> int g();
int o = g<int>(3); // ok
int p = g<int>(); // ok

// Of course once you have these two declarations at namespace scope
// you can get rid of the Dummy, TriggerADL declaration.

Ok so now lets return to the Vandevoorde example that you quoted, and now this should be easy:

#include <iostream>
class Manager { 
public:
    template<typename T> 
        friend int ticket() { 
            return ++Manager::counter; 
        } 
    static int counter; 
}; 

int Manager::counter;

template<class T> int ticket(); // <-- this should work with a conformant compiler  

int main()
{
  Manager m;
  std::cout << "ticket: " << ticket<int>() << std::endl;
}

Hope that helps :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...