简体   繁体   中英

NonTemplate Function Friend of Template Class

Can somebody explain me what I am doing wrong? This is teh error I get from the compiler.

Many Thanks

1>------ Build started: Project: Ch16, Configuration: Release Win32 ------
1>  p643_inclusion.cpp
1>  p643_inclusion_main.cpp
1>  p643_print.cpp
1>p643_print.cpp(5): error C2065: 'T1' : undeclared identifier
1>p643_print.cpp(5): error C2065: 'T2' : undeclared identifier
1>p643_print.cpp(6): warning C4552: '<<' : operator has no effect; expected operator with side-effect
1>p643_print.cpp(7): warning C4552: '<<' : operator has no effect; expected operator with side-effect
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

p643_inclusion.h

#ifndef P643H
#define P643H

template< class T1, class T2> class Car { 

    friend void  print (const Car<T1, T2> &c1);
    private:
        T1 Wheels;
        T2 DriversName;
    public:
        Car(): Wheels(4), DriversName("None") {}
        Car(T1, T2);
};



template <class T1, class T2> class Driver {
    private:
        T1 Name;
        T2 Surname;
    public:
        Driver(): Name("None"), Surname("None") {}
};


#include "p643_inclusion.cpp"

#endif

p643_inclusion.cpp

# ifndef P643CC
#define P643CC

#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
#include "p643_inclusion.h"

template<class T1, class T2>
Car<T1, T2>::Car(T1 w, T2 d) {
    Wheels = w;
    DriversName = d;
}

#endif

p643_print.cpp

#include "p643_inclusion.h"
template< class T1, class T2> class Car;

void  print (const Car<T1, T2> &c1) {
    cout << c1.Wheels << endl;
    cout << c1.DriversName << endl;
    }

main

#include "p643_inclusion.h"
#include<iostream>
#include<string>
using namespace std;


int main()
{

    Car<int, string> myCar;
    Driver<string, string> myDriver;

    print(myCar);

    return 0;
}

Your function is not actually a non-template function.

void  print (const Car<T1, T2> &c1) {
    cout << c1.Wheels << endl;
    cout << c1.DriversName << endl;
}

This is wrong. Can you ask yourself what exactly is T1 ? and T2 ?


You should implement this as:

template<class T1, class T2>
void  print (const Car<T1, T2> &c1) {
    cout << c1.Wheels << endl;
    cout << c1.DriversName << endl;
}

And you should make it friend as:

template< class T1, class T2> class Car { 

    //choose different name for type params, because enclosing class 
    //already using T1, and T2
    template<class U, class V>
    friend void  print (const Car<U, V> &c1);

    //...

Mixing templates and friendship is not always as simple as it might seem. My advice is that you define the befriended function in the class definition, and then your problem will basically go away:

template <typename T1, typename T2>
struct test {
   friend void print( test const & t ) { ... };
};

For each instantiation of the template test , it will declare and define a (non templated) free function that takes a test object instantiated with the same template arguments that triggered the instantiation of the template.

Other options available (I would stay clear of these if possible):

You can make print be a template and declare that template a friend of your class template (the whole template):

template <typename T1, typename T2>
struct test {
   template <typename U, typename V>
   friend void foo( test<U,V> const & ); // befriend template, all instantiations
};
template <typename T1, typename T2>
void foo( test<X,Y> const & x ) {...}

This opens your internals to all of the potential instantiations of the template, including possible specializations, and you might not want to do that. If you want to befriend only a particular instantiation of that template, you can do so, but it becomes more cumbersome:

template <typename T1, typename T2> struct test;  // forward declaration

template <typename T1, typename T2>
void foo( test<T1,T2> const & );                  // forward declaration

template <typename T1, typename T2>
struct test {
   friend void foo<T1,T2>( test<T1,T2> const & ); // befriend specific instantiation
};

template <typename T1, typename T2>
void foo( test<T1,T2> const & x ) { ... }         // implement

For a further explanation, you can look at the answer here

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