如何解决C++ 模板、类型名和运算符<<:错误:未定义函数模板“operator<<”的显式实例化
Universe.hpp:
// Universe Class
// damien MATTEI
#ifndef UNIVERSE_HPP
#define UNIVERSE_HPP
#include <algorithm> // used by Universe
#include <iostream>
#include <vector>
#include <list>
// Edge3D will include Point3D
#include "Edge3D.hpp"
#include "Vector3D.hpp"
#include "Object.hpp"
#include "debug.hpp"
using namespace std;
template <typename T> class Universe {
public:
// data
// name must be like containerTYPEptrCONTAINER_TYPEC (must end by a char like C or other only for macro reason (!))
// where TYPE is the element type contained in the container CONTAINER_TYPE
// example1: TYPE=Point3D,CONTAINER_TYPE=vector
std::vector< Point3D<T> *> containerPoint3DptrvectorC;
// example2: TYPE=Vector3D,CONTAINER_TYPE=vector
std::vector< Vector3D<T> *> containerVector3DptrvectorC;
// deprecated
// example3: TYPE=Edge3D,CONTAINER_TYPE=list
list < Point3D<T> *> containerPoint3DptrlistC;
list < Edge3D<T> *> containerEdge3DptrlistC;
// for deprecated compatibility in Vision3D.cpp
// the vertex
list < Point3D<T> > vertexList;
Universe();
~Universe();
// create a Point3D by checking if it already exist in the universe
template <typename ObjectType,typename... ParamTypes>
ObjectType & createPoint3DRefvectorC(ParamTypes ...args);
// create a Vector3D by checking if it already exist in the universe
template <typename ObjectType,typename... ParamTypes>
ObjectType & createVector3DRefvectorC(ParamTypes ...args);
// DEPRECATED (for tests)
Point3D<T> & createPoint3DReference(T x,T y,T z); // create a point by checking if it already exist
Point3D<T> & createPoint3Dref_BACKUP(T x,T z); // backup because i created macro that builds functions Now
// create a Point3D by checking if it already exist in the universe
template <typename ObjectType,typename... ParamTypes>
ObjectType & createPoint3DReflistC(ParamTypes ...args);
// create a Edge3D by checking if it already exist in the universe
template <typename ObjectType,typename... ParamTypes>
ObjectType & createEdge3DReflistC(ParamTypes ...args);
// create an object by checking if it already exist in the universe
// DEPRECATED
template <typename ObjectType,typename... ParamTypes>
ObjectType & createObjectRef(ParamTypes ...args);
Point3D<T> * createPoint3Dptr(T x,T z); // create a point by checking if it already exist
void createCube(Point3D<T> &,T);
// for testing
template <typename myType,typename otherType>
myType GetMax (myType a,myType b);
template <typename U>
friend std::ostream& operator<< (ostream &,const Universe<U> &);
};
template <typename U> std::ostream& operator<< (ostream &,const Universe<U> &); // does not work !!!
#endif /* UNIVERSE_HPP */
Universe.cpp:
// Universe Class
// damien MATTEI
#include "Universe.hpp"
// implementations
template <typename T> Universe<T>::Universe() {
#ifdef disPLAY_CONSTRUCTOR
cout << "# Universe constructor # " << this << endl;
#endif
}
template <typename T> Universe<T>::~Universe() {
typename vector< Point3D<T> *>::iterator it;
for(it = containerPoint3DptrvectorC.begin(); it != containerPoint3DptrvectorC.end(); it++) {
cerr << "# Universe destructor # deleting a containerPoint3DptrvectorC" << endl;
delete *it;
}
typename list< Point3D<T> *>::iterator itLst;
for(itLst = containerPoint3DptrlistC.begin(); itLst != containerPoint3DptrlistC.end(); itLst++) {
cerr << "# Universe destructor # deleting a containerPoint3DptrlistC" << endl;
delete *itLst;
}
#ifdef disPLAY_CONSTRUCTOR
cout << "# Universe destructor # " << this << endl;
#endif
}
// for testing
template <typename T>
template <typename myType,typename otherType>
myType Universe<T>::GetMax (myType a,myType b) {
// otherType i= 7; //useless
return (a>b?a:b);
}
#define CREATE_OBJECT_TEMPLATED(TYPE,TYPE_CONTAINER) \
/* create an object by checking if it already exist in the universe */ \
template <typename T> \
template <typename ObjectType,typename... ParamTypes> \
\
ObjectType & Universe<T>::create##TYPE##Ref##TYPE_CONTAINER##C(ParamTypes ...args) { \
\
DEBUG(cerr << "Universe<T>::create" #TYPE "Ref" #TYPE_CONTAINER "C<>" << endl;) \
\
ObjectType & object = *(new ObjectType(std::forward<ParamTypes>(args) ...));\
\
DEBUG(cerr << "Universe<T>::create" #TYPE "Ref" #TYPE_CONTAINER "C<> : std::find_if ... " << endl;)\
\
/* i check unicity of the object in Universe i.e to save memory and speed */ \
/* i do not want to have two mathematically identical 3D objects */ \
typename TYPE_CONTAINER < ObjectType *>::iterator iterOBJECTptr = \
std::find_if(container##TYPE##ptr##TYPE_CONTAINER##C.begin(),container##TYPE##ptr##TYPE_CONTAINER##C.end(),\
/* lambda in C++ */ \
[&object](ObjectType * object_ptr_lambda_param) { \
ObjectType & object_lambda_param = *object_ptr_lambda_param; \
DEBUG(cerr << "Universe<T>::create" #TYPE "Ref" #TYPE_CONTAINER "C<> : in Lambda" << endl;) \
return object_lambda_param == object; \
} \
); \
\
DEBUG(cerr << "Universe<T>::create" #TYPE "Ref" #TYPE_CONTAINER "C<> : bool found ... " << endl;) \
bool found = (iterOBJECTptr != container##TYPE##ptr##TYPE_CONTAINER##C.end()); \
\
\
if (found) { \
\
DEBUG(cerr << "Universe<T>::create" #TYPE "Ref" #TYPE_CONTAINER "C<> : found ... " << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "Ref" #TYPE_CONTAINER "C<> : *iterOBJECTptr " << *iterOBJECTptr << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "Ref" #TYPE_CONTAINER "C<> : **iterOBJECTptr " << **iterOBJECTptr << endl << endl;) \
\
delete &object; \
\
return **iterOBJECTptr; /* return the pointer OBJECT */ \
\
} \
else { /* we have to add the point to the universe */ \
DEBUG(cerr << "Universe<T>::create" #TYPE "Ref" #TYPE_CONTAINER "C<> : NOT found ... " << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "Ref" #TYPE_CONTAINER "C<> : container" #TYPE "ptr" #TYPE_CONTAINER "C.push_back(&object);" << endl << endl;) \
\
container##TYPE##ptr##TYPE_CONTAINER##C.push_back(&object); \
\
return object; \
} \
\
}
CREATE_OBJECT_TEMPLATED(Point3D,vector)
CREATE_OBJECT_TEMPLATED(Vector3D,vector)
// DEPRECATED
// this create the Template only for Point3D (not a particular instance for float by example)
// example of call : univ.createPoint3DRef<Point3D<float>,float,float>(1,0);
CREATE_OBJECT_TEMPLATED(Point3D,list)
CREATE_OBJECT_TEMPLATED(Edge3D,list)
// create an object by checking if it already exist in the universe
// warning: works only with Point3D as the container containerPoint3DptrlistC is statically defined
// DEPRECATED i suppose
template <typename T>
template <typename ObjectType,typename... ParamTypes>
ObjectType & Universe<T>::createObjectRef(ParamTypes ...args) {
DEBUG(cerr << "Universe<T>::createObjectRef" << endl;)
ObjectType & object = *(new ObjectType(std::forward<ParamTypes>(args) ...));
//ObjectType & object = *(new ObjectType());
DEBUG(cerr << "Universe<T>::createObjectRef : std::find_if ... " << endl;)
// i check unicity of the point in Universe i.e to save memory and speed
// i do not want to have two mathematically identical 3D points
typename list< ObjectType *>::iterator iterOBJECTptr =
std::find_if(containerPoint3DptrlistC.begin(),containerPoint3DptrlistC.end(),// lambda in C++
[&object](ObjectType * object_ptr_lambda_param) {
ObjectType & object_lambda_param = *object_ptr_lambda_param;
DEBUG(cerr << "Universe<T>::createObjectRef : in Lambda" << endl;)
return object_lambda_param == object;
}
);
DEBUG(cerr << "Universe<T>::createObjectRef : bool found ... " << endl;)
bool found = (iterOBJECTptr != containerPoint3DptrlistC.end());
if (found) {
DEBUG(cerr << "Universe<T>::createObjectRef : found ... " << endl;)
DEBUG(cerr << "Universe<T>::createObjectRef : *iterOBJECTptr " << *iterOBJECTptr << endl;)
DEBUG(cerr << "Universe<T>::createObjectRef : **iterOBJECTptr " << **iterOBJECTptr << endl;)
delete &object;
return **iterOBJECTptr; // return the pointer to OBJECT
}
else { // we have to add the point to the universe
DEBUG(cerr << "Universe<T>::createObjectRef : NOT found ... " << endl;)
DEBUG(cerr << "Universe<T>::createObjectRef : containerPoint3DptrlistC.push_back(&object);" << endl;)
containerPoint3DptrlistC.push_back(&object);
return object;
}
}
// create a point by checking if it already exists in the universe
// DEPRECATED
template<typename T> Point3D<T> & Universe<T>::createPoint3Dref_BACKUP(T x,T z) {
DEBUG(cerr << "Universe<T>::createPoint3Dref" << endl;)
Point3D<T> & pt3d = *(new Point3D<T>(x,y,z));
DEBUG(cerr << "Universe<T>::createPoint3Dref : std::find_if ... " << endl;)
// i check unicity of the point in Universe i.e to save memory and speed
// i do not want to have two mathematically identical 3D points
typename list< Point3D<T> *>::iterator iterP3Dptr =
std::find_if(containerPoint3DptrlistC.begin(),// lambda in C++
[&pt3d](Point3D<T> * pt3d_ptr_lambda_param) {
Point3D<T> & pt3d_lambda_param = *pt3d_ptr_lambda_param;
DEBUG(cerr << "Universe<T>::createPoint3Dref : in Lambda" << endl;)
//return *pt3d_ptr_lambda_param == pt3d;
return pt3d_lambda_param == pt3d;
}
);
DEBUG(cerr << "Universe<T>::createPoint3Dref : bool found ... " << endl;)
bool found = (iterP3Dptr != containerPoint3DptrlistC.end());
if (found) {
DEBUG(cerr << "Universe<T>::createPoint3Dref : found ... " << endl;)
DEBUG(cerr << "Universe<T>::createPoint3Dref : *iterP3Dptr " << *iterP3Dptr << endl;)
DEBUG(cerr << "Universe<T>::createPoint3Dref : **iterP3Dptr " << **iterP3Dptr << endl;)
delete &pt3d;
//return static_cast<Point3D<T> &> (*iterP3Dptr); // return the pointer to Point3D
//return reinterpret_cast<Point3D<T> &> (*iterP3Dptr); // return the pointer to Point3D
//return static_cast<Point3D<T> &> (**iterP3Dptr); // return the pointer to Point3D
return **iterP3Dptr; // return the pointer to Point3D
}
else { // we have to add the point to the universe
DEBUG(cerr << "Universe<T>::createPoint3Dptr : NOT found ... " << endl;)
DEBUG(cerr << "Universe<T>::createPoint3Dref : containerPoint3DptrlistC.push_back(&pt3d);" << endl;)
containerPoint3DptrlistC.push_back(&pt3d);
return pt3d;
}
}
// create an object by checking if it already exist in the universe
// DEPRECATED
#define CREATE_OBJECT(FUNCTION_NAME,TYPE,CONTAINER,PARENTHESIS_ARGS,TYPED_ParaMS...) template<typename T> TYPE & Universe<T>::FUNCTION_NAME(TYPED_ParaMS) { \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref" << endl;) \
TYPE & object = *(new TYPE PARENTHESIS_ARGS); \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : std::find_if ... " << endl;) \
typename list< TYPE *>::iterator iterObjectptr = \
std::find_if( CONTAINER.begin(),CONTAINER.end(),\
[&object](TYPE * object_ptr_lambda_param) { \
TYPE & object_lambda_param = *object_ptr_lambda_param; \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : in Lambda" << endl;) \
return object_lambda_param == object; \
} \
); \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : bool found ... " << endl;) \
bool found = (iterObjectptr != CONTAINER.end()); \
if (found) { \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : found ... " << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : *iterObjectptr " << *iterObjectptr << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : **iterObjectptr " << **iterObjectptr << endl;) \
delete &object; \
return **iterObjectptr; \
} \
else { \
DEBUG(cerr << "Universe<T>::create" #TYPE "ptr : NOT found ... " << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : CONTAINER.push_back(object_ptr);" << endl;) \
CONTAINER.push_back(&object); \
return object; \
} \
}
//CREATE_OBJECT(createPoint3Dref,Point3D<T>,containerPoint3DptrlistC,(x,z),T x,T z);
// create an object by checking if it already exist in the universe
// this a better version than CREATE_OBJECT,this macro use less parameters
#define CREATE_OBJECT_TYPE(TYPE,TYPED_ParaMS...) template<typename T> TYPE<T> & Universe<T>::create##TYPE##ref(TYPED_ParaMS) { \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref" << endl;) \
TYPE<T> & object = *(new TYPE<T> PARENTHESIS_ARGS); \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : std::find_if ... " << endl;) \
typename list< TYPE<T> *>::iterator iterObjectptr = \
std::find_if( CONTAINER.begin(),\
[&object](TYPE<T> * object_ptr_lambda_param) { \
TYPE<T> & object_lambda_param = *object_ptr_lambda_param; \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : in Lambda" << endl;) \
return object_lambda_param == object; \
} \
); \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : bool found ... " << endl;) \
bool found = (iterObjectptr != CONTAINER.end()); \
if (found) { \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : found ... " << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : *iterObjectptr " << *iterObjectptr << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : **iterObjectptr " << **iterObjectptr << endl;) \
delete &object; \
return **iterObjectptr; \
} \
else { \
DEBUG(cerr << "Universe<T>::create" #TYPE "ptr : NOT found ... " << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "ref : CONTAINER.push_back(object_ptr);" << endl;) \
CONTAINER.push_back(&object); \
return object; \
} \
}
// DEPRECATED
//#define CONCATENATE(x,y) x##y
//CREATE_OBJECT_TYPE(Point3D,T z);
// create an object by checking if it already exist in the universe
// this another better version than CREATE_OBJECT,this macro use again less parameters
// DEPRECATED
#define CREATE_OBJECT_TYPED(TYPE,TYPED_ParaMS...)\
template<typename T> TYPE<T> & Universe<T>::create##TYPE##Reference(TYPED_ParaMS) { \
DEBUG(cerr << "Universe<T>::create" #TYPE "Reference" << endl;) \
TYPE<T> & object = *(new TYPE<T> PARENTHESIS_ARGS); \
DEBUG(cerr << "Universe<T>::create" #TYPE "Reference : std::find_if ... " << endl;) \
typename list< TYPE<T> *>::iterator iterObjectptr = \
std::find_if( container##TYPE##ptrlistC.begin(),container##TYPE##ptrlistC.end(),\
[&object](TYPE<T> * object_ptr_lambda_param) { \
TYPE<T> & object_lambda_param = *object_ptr_lambda_param; \
DEBUG(cerr << "Universe<T>::create" #TYPE "Reference : in Lambda" << endl;) \
return object_lambda_param == object; \
} \
); \
DEBUG(cerr << "Universe<T>::create" #TYPE "Reference : bool found ... " << endl;) \
bool found = (iterObjectptr != container##TYPE##ptrlistC.end()); \
if (found) { \
DEBUG(cerr << "Universe<T>::create" #TYPE "Reference : found ... " << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "Reference : *iterObjectptr " << *iterObjectptr << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "Reference : **iterObjectptr " << **iterObjectptr << endl;) \
delete &object; \
return **iterObjectptr; \
} \
else { \
DEBUG(cerr << "Universe<T>::create" #TYPE "ptr : NOT found ... " << endl;) \
DEBUG(cerr << "Universe<T>::create" #TYPE "Reference : container???.push_back(object_ptr);" << endl;) \
container##TYPE##ptrlistC.push_back(&object); \
return object; \
} \
}
// example: univ.createPoint3DReference(1,0);
CREATE_OBJECT_TYPED(Point3D,T z);
// create a point by checking if it already exist in the universe
template<typename T> Point3D<T> * Universe<T>::createPoint3Dptr(T x,T z) {
DEBUG(cerr << "Universe<T>::createPoint3Dptr" << endl;)
Point3D<T> * pt3d_ptr = new Point3D<T>(x,z);
Point3D<T> & pt3d = *pt3d_ptr;
DEBUG(cerr << "Universe<T>::createPoint3Dptr : std::find_if ... " << endl;)
// i check unicity of the point in Universe i.e to save memory and speed
// i do not want to have two mathematically identical 3D points
typename list< Point3D<T> *>::iterator iterP3Dptr =
std::find_if(containerPoint3DptrlistC.begin(),// lambda in C++
[&pt3d](Point3D<T> * pt3d_ptr_lambda_param) {
Point3D<T> & pt3d_lambda_param = *pt3d_ptr_lambda_param;
DEBUG(cerr << "Universe<T>::createPoint3Dptr : in Lambda" << endl;)
//return *pt3d_ptr_lambda_param == pt3d;
return pt3d_lambda_param == pt3d;
}
);
DEBUG(cerr << "Universe<T>::createPoint3Dptr : bool found ... " << endl;)
bool found = (iterP3Dptr != containerPoint3DptrlistC.end());
if (found) {
DEBUG(cerr << "Universe<T>::createPoint3Dptr : found ... " << endl;)
DEBUG(cerr << "Universe<T>::createPoint3Dptr : *iterP3Dptr " << *iterP3Dptr << endl;)
DEBUG(cerr << "Universe<T>::createPoint3Dptr : **iterP3Dptr " << **iterP3Dptr << endl;)
delete pt3d_ptr;
//return static_cast<Point3D<T> &> (*iterP3Dptr); // return the pointer to Point3D
//return reinterpret_cast<Point3D<T> &> (*iterP3Dptr); // return the pointer to Point3D
//return static_cast<Point3D<T> &> (**iterP3Dptr); // return the pointer to Point3D
return *iterP3Dptr; // return the pointer to Point3D
}
else { // we have to add the point to the universe
DEBUG(cerr << "Universe<T>::createPoint3Dptr : NOT found ... " << endl;)
DEBUG(cerr << "Universe<T>::createPoint3Dptr : containerPoint3DptrlistC.push_back(pt3d_ptr);" << endl;)
containerPoint3DptrlistC.push_back(pt3d_ptr);
return pt3d_ptr;
}
}
// params: point,edge length
template<typename T> void Universe<T>::createCube(Point3D<T> & p,T s) {
// horizontal edges
Point3D<T> & p2 = createPoint3DReflistC<Point3D<T>,T,T>(p.x+s,p.y,p.z); // bottom,right x
createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p,p2);
Point3D<T> & p3 = createPoint3DReflistC<Point3D<T>,p.y+s,right x,left y
createEdge3DReflistC<Edge3D<T>,Point3D<T> &>(p2,p3);
Point3D<T> & p4 = createPoint3DReflistC<Point3D<T>,T>(p.x,Point3D<T> &>(p3,p4);
createEdge3DReflistC<Edge3D<T>,p4);
Point3D<T> & ptop = createPoint3DReflistC<Point3D<T>,p.z+s);
Point3D<T> & p2top = createPoint3DReflistC<Point3D<T>,ptop.z); // top,p2top);
Point3D<T> & p3top = createPoint3DReflistC<Point3D<T>,Point3D<T> &>(p2top,p3top);
Point3D<T> & p4top = createPoint3DReflistC<Point3D<T>,Point3D<T> &>(p3top,p4top);
createEdge3DReflistC<Edge3D<T>,Point3D<T> &>(ptop,p4top);
// vertical edges
createEdge3DReflistC<Edge3D<T>,ptop);
createEdge3DReflistC<Edge3D<T>,p2top);
createEdge3DReflistC<Edge3D<T>,p3top);
createEdge3DReflistC<Edge3D<T>,Point3D<T> &>(p4,p4top);
}
// DEPRECATED
//template Point3D<float> & Universe<float>::createObjectRef(float,float) ; // works too
template Point3D<float> & Universe<float>::createObjectRef<Point3D<float>,float>(float,float) ;
//template int Universe<float>::createObjectRef<int,float) ;
template <typename U>
std::ostream& operator<< (std::ostream &out,Universe<U> &u)
{
out << "Universe :"
<< &u
<< " "
;
return out;
}
template class Universe<float>;
// for tests
//template int Universe<float>::GetMax( int,int ) ; // works too
template int Universe<float>::GetMax<int,float>( int,int );
// call by : univ.createPoint3DReflistC<Point3D<float>,0);
template Point3D<float> & Universe<float>::createPoint3DReflistC<Point3D<float>,float) ;
template Edge3D<float> & Universe<float>::createEdge3DReflistC<Edge3D<float>,Point3D<float>&,Point3D<float>&>(Point3D<float>&,Point3D<float>&) ;
template Point3D<float> & Universe<float>::createPoint3DRefvectorC<Point3D<float>,float) ;
template Vector3D<float> & Universe<float>::createVector3DRefvectorC<Vector3D<float>,float) ;
template std::ostream& operator<< (std::ostream &,const Universe<float> &); // does not work
(base) albedo-2:vision3D mattei$ make 编译 Universe.cpp g++ -c -o Universe.o Universe.cpp -Wall -std=c++17 -I. -DDEBUG_BUILD -DdisPLAY_CONSTRUCTOR -DCHECK_MEMORY Universe.cpp:468:25: 错误:未定义函数模板“operator
解决方法
这是您声明的函数模板:
template <typename U>
std::ostream& operator<< (ostream &,const Universe<U> &);
这是你实现的功能模板:
template <typename U>
std::ostream& operator<< (std::ostream &out,Universe<U> &u) {...}
你能看出区别吗?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。