简体   繁体   中英

Redefinition error when defining friend function inside class template

I am learning friend declarations in C++ using the books listed here . So after reading, to test my understanding of the concept, i wrote the following program whose output i am unable to understand:

template<typename T>
struct Name
{
  
  friend void anotherFeed(int x)//anotherFeed is implicitly inline and its definition is generate only when we use this nonmember function so why are we getting error at instiantiation?
  {
  }
 
};
int main()
{
    Name<int> s;
    Name<double> p;//error here. My question is that this is instiantiation of the class template Name<double> and not a call to anotherFeed so why do we get error here?
}

The above program give the following error:

error: redefinition of ‘void anotherFeed(int)’

This is my current understanding:

  1. The friend non-member function anotherFeed(int) is implicitly inline .
  2. Even if anotherFeed(int) is inline , we cannot define the same function(doesn't matter inline or not) in the same translation unit.
  3. The definition of anotherFeed(int) is generated only when we use/call this function just like for a nontemplate member function of a class template.

My question is that: Assuming that my understanding(the above 3 points) are correct, since i have not called/used anotherFeed so its definition should not be generated and we should not get the redefinition error at the time of creating an instance of the class template. Only when we call anotherFeed using those instances, we should get the redefinition error. So why do we get error at the time of creating class template's instance. Is there anything wrong in any of the above 3 points.

Summary

I read that the definitions for these functions(non template member functions and friend non template functions) are instantiated only when used. That is,

Name<int> s;    
Name<double> p; //this should work in principle because this does not instantiate the definition of anotherFeed(int)

But this doesn't happen. Why/How?

The free function

friend void anotherFeed(int x){}

is not dependent on the template parameter, hence, there is only this one free function which is defined twice in your example. Make it a forward declaration only

template<typename T>
struct Name {
    friend void anotherFeed(int x);
};

and define it outside the class definition

void anotherFeed(int x) {}

and all's well.

For a function template, its declaration can be instantiated without instantiating its definition.

This instantiates everything except the function body (more or less).

The declaration of your function is instantiated when the class is instantiated . When (and if) you actually call the function, its definition is instantiated.

I can't find the right standard quote, but apparently the compiler doesn't need to instantiate the definitions to reject the duplicate instantiated declarations.

From temp.inst/5

A function whose declaration was instantiated from a friend function definition is implicitly instantiated when it is referenced in a context that requires a function definition to exist or if the existence of the definition affects the semantics of the program.

So when you wrote:

Name<int> s; //only the declaration(and not the definition) of the friend function `anotherFeed(int)` is intantiated due to this statment 

Next,

Name<double> p; // here also only the declaration(and not the definition) of the friend function `anotherFeed(int)` is intantiated

Both of the above statements have the affect of instantiation of only the declaration (and not the definition) of the friend function anotherFeed(int) . And having multiple declarations(as opposed to definition) is perfectly fine.

Now, note that this declaration was instantiated using the friend function's definition but since it is not referenced in a context that requires a function definition to exist and neither the existence of the definition affects the semantics of the program, so according to the quoted statement at the beginning of my answer, the program should work without giving an error .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM