为什么 g++ 需要模板 class 及其友元函数的定义?
why does g++ need both definitions of template class and its friend function?
我想为模板编写友元函数class。
在visual studio中,我可以忽略预定义两者。
但在 g++ 中,它是强制性的。
为什么?
#include <iostream>
using namespace std;
// g++ needs, vs do not needs
template <class T>
class A;
template <class T>
ostream & operator<<(ostream & c, const A<T> & v);
//- end of g++ needs
template <class T>
class A {
T _v;
public:
A() {}
A(T v) : _v(v) {}
friend ostream & operator<<<T>(ostream & c, const A<T> & v);
};
template <class T>
ostream & operator<<(ostream & c, const A<T> & v) {
c << v._v; return c;
}
因为
friend ostream & operator<<<T>(ostream & c, const A<T> & v);
是
的特化
template <class T>
ostream & operator<<(ostream & c, const A<T> & v);
你需要先声明,然后
A<T>
部分意味着您必须在运算符声明之前也声明它
template <class T>
class A;
所以VS可能是错的C++14
14.5.4 Friends [temp.friend]
举个例子
template<class T> class task;
template<class T> task<T>* preempt(task<T>*);
template<class T> class task {
friend void next_time();
friend void process(task<T>*);
friend task<T>* preempt<T>(task<T>*);
template<class C> friend int func(C);
friend class task<int>;
template<class P> friend class frd;
};
你的例子符合第三个朋友声明。
MSVC 模板代码从根本上被破坏了。他们在过去几年一直在重建它,但它仍然包含您所观察到的怪癖。这是因为它被构建为几乎类似于宏,而不是 C++ 标准所要求的。
在 gcc 中,您可以通过在 class:
的主体中内联定义 <<
运算符来取消前向声明
friend std::ostream& operator<<(std::ostream& c, const A& v){
c << v._v;
return c;
}
这样做的好处是 <<
不再是 template
,而是为模板 A
的每个实例创建的独特的非模板。在某些情况下,这往往会更好。
我想为模板编写友元函数class。 在visual studio中,我可以忽略预定义两者。 但在 g++ 中,它是强制性的。 为什么?
#include <iostream>
using namespace std;
// g++ needs, vs do not needs
template <class T>
class A;
template <class T>
ostream & operator<<(ostream & c, const A<T> & v);
//- end of g++ needs
template <class T>
class A {
T _v;
public:
A() {}
A(T v) : _v(v) {}
friend ostream & operator<<<T>(ostream & c, const A<T> & v);
};
template <class T>
ostream & operator<<(ostream & c, const A<T> & v) {
c << v._v; return c;
}
因为
friend ostream & operator<<<T>(ostream & c, const A<T> & v);
是
的特化template <class T>
ostream & operator<<(ostream & c, const A<T> & v);
你需要先声明,然后
A<T>
部分意味着您必须在运算符声明之前也声明它
template <class T>
class A;
所以VS可能是错的C++14
14.5.4 Friends [temp.friend]
举个例子
template<class T> class task;
template<class T> task<T>* preempt(task<T>*);
template<class T> class task {
friend void next_time();
friend void process(task<T>*);
friend task<T>* preempt<T>(task<T>*);
template<class C> friend int func(C);
friend class task<int>;
template<class P> friend class frd;
};
你的例子符合第三个朋友声明。
MSVC 模板代码从根本上被破坏了。他们在过去几年一直在重建它,但它仍然包含您所观察到的怪癖。这是因为它被构建为几乎类似于宏,而不是 C++ 标准所要求的。
在 gcc 中,您可以通过在 class:
的主体中内联定义<<
运算符来取消前向声明
friend std::ostream& operator<<(std::ostream& c, const A& v){
c << v._v;
return c;
}
这样做的好处是 <<
不再是 template
,而是为模板 A
的每个实例创建的独特的非模板。在某些情况下,这往往会更好。