模板类的非模板函数友元

发布于 2024-10-31 03:59:45 字数 2075 浏览 3 评论 0原文

有人可以解释一下我做错了什么吗?这是我从编译器得到的错误。

非常感谢

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

要走干脆点 2024-11-07 03:59:45

您的函数实际上不是非模板函数。

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

    //...

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

    //...
忱杏 2024-11-07 03:59:45

混合模板和友谊并不总是像看起来那么简单。我的建议是,您在类定义中定义 befriended 函数,然后您的问题基本上就会消失:

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

有关进一步的解释,您可以查看答案 此处

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文