Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8347493
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 9, 20262026-06-09T07:22:40+00:00 2026-06-09T07:22:40+00:00

c++ faq 35.16 http://www.parashift.com/c++-faq-lite/template-friends.html #include <iostream> template<typename T> class Foo { public: Foo(T const&

  • 0

c++ faq 35.16

http://www.parashift.com/c++-faq-lite/template-friends.html

#include <iostream>

template<typename T>
class Foo {
public:
  Foo(T const& value = T());
  friend Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs);
  friend std::ostream& operator<< (std::ostream& o, const Foo<T>& x);
private:
  T value_;
};

The autor claims:

‘The snag happens when the compiler sees the friend lines way up in the class definition proper. At that moment it does not yet know the friend functions are themselves templates (why is it? aren’t class template member functions be function template by default?); it assumes they are non-templates like this:’

Foo<int> operator+ (const Foo<int>& lhs, const Foo<int>& rhs)
{ ... }  

std::ostream& operator<< (std::ostream& o, const Foo<int>& x)
{ ... }

Why are the above non-templates? aren’t these templates that are instantiated via int?

‘When you call the operator+ or operator<< functions, this assumption causes the compiler to generate a call to the non-template functions, but the linker will give you an “undefined external” error because you never actually defined those non-template functions. ‘

In fact, to make compiler recognize the above as function template, programmer has to do this explicitly like below:

template<typename T> class Foo;  // pre-declare the template class itself
template<typename T> Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs);
template<typename T> std::ostream& operator<< (std::ostream& o, const Foo<T>& x);

Could anyone explain? I find this quite vexing and do not know why compiler does not just instantiate a instance of Class Foo by replacing T with ‘int’, and call it a day.

Thanks.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-09T07:22:42+00:00Added an answer on June 9, 2026 at 7:22 am

    Class template member functions are part of the template and are therefore instantiated with the template, but friends are not. Consider the non-template case:

    struct S {
        friend void foo(S);
    };
    

    Note that void foo(S) does not have to be declared at this point; the friend declaration is saying that if a function void foo(S) is defined, then that function will have access to S. It might never actually be defined, and that’s fine.

    With templates, the situation is the same:

    template<typename T> struct S {
        friend void foo(S);
    };
    

    This is saying that for any type T, if a function void foo(S<T>) is defined then that function has access to S<T>. That function is expected to be a concrete function, by overloading:

    void foo(S<char>) { }
    void foo(S<int>) { }
    

    The compiler doesn’t know that you are planning later on to supply a function template that can be used for all T. Instead, if an appropriate function template is already declared then it will be instantiated if you specify that it should by adding angle brackets.

    As for why you have to forward-declare the template, there’s no reason that “the template” has to have just one declaration. Consider:

    #include <iostream>
    template<typename T> struct S;
    template<typename T> void foo(S<T>);
    template<typename T> void foo(S<T *>);
    template<typename T> struct S {
        friend void foo<>(S);
    };
    template<typename T> void foo(S<T>) { std::cout << "template template friend\n"; }
    template<typename T> void foo(S<T *>) { std::cout << "template specialization template friend\n"; }
    template void foo(S<void *>);
    int main() {
        foo(S<int>());
        foo(S<void *>());
    }
    

    Here there are two specialisations of foo, and they have to both be forward declared so that the friend can select between them.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html class BadConversion : public std::runtime_error { public: BadConversion(std::string const& s) : std::runtime_error(s)
The question is from C++ faq. http://www.parashift.com/c++-faq-lite/protected-virtuals.html Code using public overloaded virtuals: class Base
In http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.6 , it is wriiten that Another valid approach would be to define
I know destructor shouldn't not throw exception. http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.13 I have the following code :
I have a question based on this question In the section http://www.parashift.com/c%2B%2B-faq-lite/private-inheritance.html#faq-24.3 the following
From http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.14 : Even if the language outlawed const_cast , the only way to
From: http://www.parashift.com/c++-faq-lite/basics-of-inheritance.html#faq-19.9 Three keys: ROI, ROI and ROI. Every interface you build has a
I was reading some C++ text at the address: http://www.parashift.com/c++-faq-lite/new/istream-and-while.html . According to the
From c++ FAQ: http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.9 Remember: delete p does two things: it calls the destructor
From http://www.parashift.com/c++-faq-lite/basics-of-inheritance.html#faq-19.5 A member (either data member or member function) declared in a protected

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.