C++ 模板化算子的奇异行为
我无法理解操作符的行为您应该学习如何将其归结为一个简单的工作示例 下面是一个SSCCE,它演示了问题:C++ 模板化算子的奇异行为,c++,templates,operator-overloading,friend,C++,Templates,Operator Overloading,Friend,我无法理解操作符的行为您应该学习如何将其归结为一个简单的工作示例 下面是一个SSCCE,它演示了问题: #include <iostream> template<class T> class Vector { private: T m; public: Vector(T p) : m(p) {} friend std::ostream& operator<<(std::ostream& o, Vector<T
#include <iostream>
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
T get() const { return m; }
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T>& v)
{
// accessing a private member leads to a compiler error here:
return o << "[function template]" << /*v.m*/ v.get();
}
// remove this function to get the same behaviour as in the OP
std::ostream& operator<<(std::ostream& o, Vector<int> const& v)
{
return o << "function" << v.m;
}
int main()
{
Vector<int> v(42);
std::cout << v;
}
使用正向声明的解决方案:
template<class T>
class Vector;
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<< <T>(std::ostream& o, Vector<T> const& v);
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
现在,编译器可以找到前向声明的函数模板,并通过函数模板的专门化而不是声明新函数来与现有函数成为朋友
使整个函数模板友好的解决方案:
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
template<class U>
friend std::ostream& operator<<(std::ostream& o, Vector<U> const& v);
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
在这个解决方案中,friend声明声明了一个函数模板,随后在类的定义后面的命名空间范围中的声明重新声明了这个函数模板。您的main是在vector.cpp还是其他一些cpp文件中?@MichaelBurr在main.cpp中。看看这些编辑。从大到大,我只是为了满足我的好奇心,顺便回答一下你的问题。通过。@wingsofnia似乎这个问题有你如何摆脱警告的答案:谢谢你,@dyp。你喜欢什么样的解决方案?最佳实践是什么?不确定这里的最佳实践是什么。通常,我会在类定义中实现类模板的短成员函数。但是,如果您想保持类定义和成员函数定义严格分开,可以使用第二种解决方案和前向声明。我不会使用第三个,因为它适合所有专业。顺便说一句,包括一个.cpp看起来很奇怪;一些库(如boost)使用.ipp作为模板的实现部分,使用.hpp作为普通头文件。
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
Vector<int> v;
v.add(1);
v.add(2);
cout << v << endl; // v is not const
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
};
template<class T>
class Vector;
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v);
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
friend std::ostream& operator<< <T>(std::ostream& o, Vector<T> const& v);
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}
template<class T>
class Vector
{
private:
T m;
public:
Vector(T p) : m(p) {}
template<class U>
friend std::ostream& operator<<(std::ostream& o, Vector<U> const& v);
};
template<class T>
std::ostream& operator<<(std::ostream& o, Vector<T> const& v)
{
return o << v.m;
}