C++ 在模板类中定义友元函数

C++ 在模板类中定义友元函数,c++,templates,friend,C++,Templates,Friend,我使用三个不同的文件来定义模板类。类声明在.h文件中,实现在.cpp文件中,显式实例化包含在.inc文件中。 我试图定义一个friend函数,它能够访问模板类的私有数据成员。 与模板类一样,函数将在3个单独的文件中定义、实现和实例化。 当我尝试调用该函数时,会收到以下错误消息: 错误:“doSomething”既不是函数也不是成员函数;不能被宣布为朋友 myclass.h:错误:应为“;”在这之前,我认为这应该行得通 template<class T> class MyClass;

我使用三个不同的文件来定义模板类。类声明在.h文件中,实现在.cpp文件中,显式实例化包含在.inc文件中。 我试图定义一个friend函数,它能够访问模板类的私有数据成员。 与模板类一样,函数将在3个单独的文件中定义、实现和实例化。 当我尝试调用该函数时,会收到以下错误消息:

错误:“doSomething”既不是函数也不是成员函数;不能被宣布为朋友


myclass.h:错误:应为“;”在这之前,我认为这应该行得通

template<class T>
class MyClass;

template <class T>
T doSomething( const MyClass<T> *, T, int);

template<class T>
class MyClass {
  friend T doSomething<T>( const MyClass<T> *, T, int);
public:
  ...
private:
  T *m_pMyMatrix;
};

也就是说,您需要先声明模板,然后才能使其或其实例成为好友

我认为这应该行得通

template<class T>
class MyClass;

template <class T>
T doSomething( const MyClass<T> *, T, int);

template<class T>
class MyClass {
  friend T doSomething<T>( const MyClass<T> *, T, int);
public:
  ...
private:
  T *m_pMyMatrix;
};
也就是说,您需要先声明模板,然后才能使其或其实例成为好友

我想我解决了这个问题:

mymethod.h

myclass.h

mymethod.cpp

实际上,您只需要在MyClass定义之前声明模板函数。

我想我解决了这个问题:

mymethod.h

myclass.h

mymethod.cpp



实际上,您只需要在MyClass定义之前声明模板函数。

@Javier:现在试试,我已经更正了模板函数声明中不应使用的code friend关键字。@David:谢谢。我没有仔细看就复制了声明。@Javier:在将函数模板声明为朋友之前,您无法绕过声明它,您必须声明类模板才能声明函数模板。但是,您可以稍后定义该模板。编译器对friend的所有需求都是函数模板的声明,而编译器对friend的所有需求都是类模板的声明。如果doSomething friend函数现在有一个Foo类型的新参数,我该怎么办?我应该在MyClass和Foo类的两个类定义中将doSomething定义为friend吗?@Javier:我看到Simone已经在帮助你了。到目前为止,我完全同意他所写的一切,如果我再重复一遍,那就没有意义了。@Javier:现在试试,我已经更正了模板函数声明中不应使用的code friend关键字。@David:谢谢。我没有仔细看就复制了声明。@Javier:在将函数模板声明为朋友之前,您无法绕过声明它,您必须声明类模板才能声明函数模板。但是,您可以稍后定义该模板。编译器对friend的所有需求都是函数模板的声明,而编译器对friend的所有需求都是类模板的声明。如果doSomething friend函数现在有一个Foo类型的新参数,我该怎么办?我应该在MyClass和Foo类的两个类定义中将doSomething定义为friend吗?@Javier:我看到Simone已经在帮助你了。到目前为止,我完全同意他所写的一切,如果我重复一遍,这将使它变得毫无意义。您需要在类定义之前将mymethod.h包含在myclass.h中,并在类myclass的定义之外删除friend声明。@Javier:您不需要函数定义,只需要声明即可。基本上,在定义MyClass之前,必须向前声明MyClass模板,然后声明doSomething模板函数。实际实现可以放在任何地方。通常情况下,如果在单个头文件中提供模板,生活会容易得多,但在某些情况下,编译时不这样做是有原因的,修复可以用作模板实例化的类型-例如,无法使用其他类型实例化模板…我认为您不能与未声明的函数模板交朋友。在g++3.4.5中编译。另外,它是一个未定义的函数,而不是未声明的函数。模板类和模板函数耦合得太厉害,将它们分开是没有意义的。您需要在类定义之前将mymethod.h包含在myclass.h中,并删除类myclass定义之外的友元声明。@Javier:您不需要函数定义,只需要声明。基本上,在定义MyClass之前,必须向前声明MyClass模板,然后声明doSomething模板函数。实际实现可以放在任何地方。通常情况下,如果在单个头文件中提供模板,生活会容易得多,但在某些情况下,编译时不这样做是有原因的,修复可以用作模板实例化的类型-例如,无法使用其他类型实例化模板…我认为您不能与未声明的函数模板交朋友。在g++3.4.5中编译。而且,它是一个
未定义的函数,不是未声明的。顺便说一下,我会将两个头文件合并到一个头文件中。templated类和template函数是如此耦合,将它们分开是没有意义的。使用friend函数可能会很危险!任何人都可以编写具有相同签名的静态函数并获得对类的控制权,除非您的友元函数是用名称空间声明的。@Edwin:我想这属于防止Murphy guy获得控制权的旧规则,反对Macchiavelli无论如何都是徒劳的。@sbi:我只是说,当你使用友人函数时,你奉献了一个已知的可信实体,确保你的友人是你真正想要的人。猜猜你想要什么。使用朋友函数可能很危险!任何人都可以编写具有相同签名的静态函数并获得对类的控制权,除非您的友元函数是用名称空间声明的。@Edwin:我想这属于防止Murphy guy获得控制权的旧规则,反对Macchiavelli无论如何都是徒劳的。@sbi:我只是说,当你使用友人函数时,你奉献了一个已知的可信实体,确保你的友人是你真正想要的人。猜猜你想要什么。
#include <mymethod.h>
template <class T>
T doSomething( MyClass<T> * pData, T val, int index){
   // the actual code does sth. more complex than the code below.
   pData->m_pMyMatrix[index]+=val;
   return pData->m_pMyMatrix[index];
}

template <class T>
MyClass<T>* doSomethingElse(const MyClass<T> * pData1, const MyClass<T> * pData2){
   ...
   T res1 = doSomething(pData1, val1, index1);
   ...
}
#include "mymethod-impl.inc"
template float doSomething( MyClass<float> *, float, int);
template double doSomething( MyClass<double> *, double, int);

template MyClass<float>* doSomethingElse(const MyClass<float>*, const MyClass<float>*);
template MyClass<double>* doSomethingElse(const MyClass<double>*, const MyClass<double> *);
template<class T>
class MyClass;

template <class T>
T doSomething( const MyClass<T> *, T, int);

template<class T>
class MyClass {
  friend T doSomething<T>( const MyClass<T> *, T, int);
public:
  ...
private:
  T *m_pMyMatrix;
};
template<class T> class MyClass;

template<class T> 
T doSomething<T>(const MyClass<T>* pData, T val, int index);
#include "mymethod.h"

template<class T>
class MyClass {
    friend T doSomething<T>(const MyClass<T>* pData, T val, int index);

public:
    // ...

private:
    T *m_pMyMatrix;
};
#include "myclass.h"

template<class T>
T doSomething(const MyClass<T>* pData, T val, int index)
{
    pData->m_pMyMatrix[index]+=val;
    return pData->m_pMyMatrix[index];
}

template<> float doSomething( const MyClass<float> *, float, int);
template<> double doSomething( const MyClass<double> *, double, int);