Функция NonTemplate Друг шаблона класса - PullRequest
2 голосов
/ 05 апреля 2011

Может кто-нибудь объяснить мне, что я делаю не так? Это ошибка, которую я получаю от компилятора.

Большое спасибо

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;
    }

основной

#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;
}

Ответы [ 2 ]

4 голосов
/ 05 апреля 2011

Ваша функция на самом деле не является шаблонной функцией.

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

Это неправильно. Можете ли вы спросить себя, что именно T1? и T2?


Вы должны реализовать это как:

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

И вы должны сделать это friend как:

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);

    //...
2 голосов
/ 05 апреля 2011

Смешивать шаблоны и дружбу не всегда так просто, как может показаться. Мой совет заключается в том, чтобы вы определили функцию с поддержкой друзей в определении класса, и тогда ваша проблема в основном исчезнет:

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

Для каждого экземпляра шаблона test он будет объявлять и определять (не шаблонизированную) свободную функцию, которая принимает объект test, созданный с теми же аргументами шаблона, которые инициировали создание шаблона.

Доступны другие варианты (я бы не стал их использовать, если это возможно):

Вы можете сделать print шаблоном и объявить этот шаблон другом вашего шаблона класса (всего шаблона):

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 ) {...}

Это открывает ваши внутренние возможности для всех возможных реализаций шаблона, включая возможные специализации, и вы, возможно, не захотите этого делать. Если вы хотите подружиться только с конкретным экземпляром этого шаблона, вы можете сделать это, но он становится более громоздким:

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

Дополнительное объяснение вы можете найти в ответе здесь

...