简体   繁体   English

专业模板类的朋友(C ++)

[英]friend of specialized template class (C++)

#include <iostream>
using namespace std;
template <typename T>
class test
{
    T y;

public:
    test(T k) : y(k) {}
    friend int a(T& x);
};

template <typename T>
int a(T& x)
{
    cout << x.y;
    return 9;
}

template <>
class test<int>
{
    int y;
public:
    test(int k) : y(k) {}
    friend int a(int& x);
};

template <>
int a<int>(int& x)
{
    cout << "4";
    return 0;
}

int main(int argc, char* argv[])
{
    test<int> z(3);
    a(z);

    return 0;
}

I want to make a friend class of test class (in a real case, it was a operator<< of ofstream). 我想创建一个测试类的朋友类(在实际情况下,它是ofstream的运算符<<)。 But I have no idea how to define template friend function of specialized class. 但我不知道如何定义专门类的模板友好函数。

Besides, the code above shows this compile error message; 此外,上面的代码显示了此编译错误消息;

error C2248: 'test::y' : cannot access private member declared in class 'test' 错误C2248:'test :: y':无法访问类'test'中声明的私有成员

Question added; 问题补充;

Aaron McDaid works fine for me, but I was trying to overload operator<< of ofstream class. Aaron McDaid对我来说很好,但我试图重载运算符<< ofstream class。

friend ofstream& operator<< <test<int>> (ofstream& os, const test<int>& t);

I added code above to test class and 我在上面添加了代码来测试类和

template<>
ofstream& operator<< <test<int> > (ofstream& os, const test<int>& t)
{
    os << t.y;
    return os;
}

used code above. 使用上面的代码。 But it looks like I cannot use os << ty (which is int ) I don't understand why this happens. 但看起来我不能使用os << ty(这是int )我不明白为什么会发生这种情况。 The error message is 错误消息是

error C2027: use of undefined type 'std::basic_ofstream<_Elem,_Traits>' 错误C2027:使用未定义类型'std :: basic_ofstream <_Elem,_Traits>'

This friend isn't a template, but an ordinary function: 这位朋友不是模板,而是普通的功能:

friend int a(T& x); 

To have a template that is also a friend, try: 要拥有也是朋友的模板,请尝试:

template<class U>
friend int a(U& x); 

After the discussions in the comments, perhaps I should show that I intended these declarations for the test class and its specialization: 在评论中讨论之后,或许我应该表明我打算为test类及其专业化做出这些声明:

template <typename T>
class test
{
    T y;

public:
    test(T k) : y(k) {}

    template<class U>
    friend int a(U& x); 
};

template <>
class test<int>
{
    int y;
public:
    test(int k) : y(k) {}

    template<class U>
    friend int a(U& x); 
};

A slight disadvantage is that this makes all the a functions friends of all the test classes, but that is often not a big problem. 轻微的缺点是,这使得所有的a所有功能的朋友test类,但是这往往不是一个大问题。

( Update : Here's a fully tested version on http://ideone.com/3KGU4 . For the Additional question , see http://ideone.com/w0dLo ) 更新 :这是http://ideone.com/3KGU4上经过全面测试的版本。有关其他问题 ,请参阅http://ideone.com/w0dLo

There is a difference between ordinary overloaded functions and template functions. 普通重载函数和模板函数之间存在差异。 For example, without any reference to templates a developer can declare: 例如,在没有任何模板引用的情况下,开发人员可以声明:

void f(int x);
void f(char *x);

Alternatively, a developer could use templates, 或者,开发人员可以使用模板,

template <class T> void f(T x);

A major difference between them is that with ordinary functions, you must decide on a fixed set of allowed parameters in advance, and you must provide an implementation for each one. 它们之间的主要区别在于,对于普通函数,您必须事先确定一组固定的允许参数,并且必须为每个参数提供一个实现。 With templates, you can be more flexible. 使用模板,您可以更灵活。

Later in your program, it is clear that you want a to be a template function, not simply an (overloaded) ordinary function. 在程序的后面,很显然,你想a是一个模板函数,而不是简单的(重载)普通函数。 But when the compiler first sees mention of a (around line 10), it looks like it is declaring an ordinary function. 但是当编译器第一次看到提及a (第10行)时,它看起来像是在声明一个普通的函数。 To resolve this, you must take two steps. 要解决此问题,您必须采取两个步骤。 You must declare as soon as possible that a is a template function, so your first line should be: 您必须尽快声明a是模板函数,因此您的第一行应该是:

template <typename T> int a(T& x);

Then you must declare the relevant friendship. 那你必须宣布相关的友谊。 If T is int , then a takes a parameter of test<int>& , not int& . 如果Tint ,那么a接受test<int>&的参数,而不是int& Therefore the two friend lines should be replaced with: 因此,应将两条朋友行替换为:

friend int a<test<T> >( test<T> & x); // around line 10
friend int a<test<int> >( test<int> & x); // around line 27

and the specialization of a should be: 和专业化a应该是:

template <>
int a< test<int> >(test<int>& ) // around line 30

The Additional Question 附加问题

Use ostream instead of ofstream (or else include #include <fstream> if you will output only to files and not to cout ). 使用ostream而不是ofstream (如果只输出文件而不输出cout则使用#include <fstream> )。 In my answer, operator << is not a template, but is a normal overloaded function. 在我的回答中, operator <<不是模板,而是正常的重载函数。 I'm not sure it's possible to have operator<< as a template. 我不确定是否可以将operator<<作为模板。 Also, I defined the operator at the place where it is declared and declared as a friend. 此外,我在声明它并声明为朋友的地方定义了运算符。 To be honest, I think there are other, maybe better, ways but this worked for me. 说实话,我认为还有其他的,可能更好的方式,但这对我有用。

Try this, and it works 试试这个, 它的确有效

#include <iostream>
using namespace std;

template <typename T>
class test;

template <typename T>
int a( test<T>& x);

template <typename T>
class test
{
    T y;

public:
    test(T k) : y(k) {}
    friend int a<T>( test<T>& x);
};

template <typename T>
int a( test<T>& x)
{
    cout << x.y;
    return 9;
}

template <>
class test<int>
{
    int y;
public:
    test(int k) : y(k) {}

    friend int a<int>( test<int> & x);
};

template <>
int a< int >( test<int> & x)
{
    cout << "4";
    return 0;
}

int main(int argc, char* argv[])
{
    test<int> z(3);
    a(z);

    return 0;
}

The problem is, template function a takes a parameter of test template class. 问题是,模板函数a采用test模板类的参数。 If you want both of them to have the same template argument then , IMO you need to explicitly state that 如果你想让它们都具有相同的模板参数,那么你需要明确说明IMO

template <typename T>
    int a( test<T>& x);

Also specialization of function a for int ( template<> int a(int& x) ) isn't useful here. 函数a for inttemplate<> int a(int& x) )的特殊化在这里也没用。 You need to have 你需要拥有

template <> int a<int>( test<int> & x)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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