dimanche 30 mai 2021

C++ template,typename and operator<< : error: explicit instantiation of undefined function template 'operator<<'

error is in the title, here is the code :

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 y,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 y,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,float>(1,0,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 y,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(), containerPoint3DptrlistC.end(),
         // 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,y,z),T x,T y,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,CONTAINER,PARENTHESIS_ARGS,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(), CONTAINER.end(), \
              [&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,containerPoint3DptrlistC,(x,y,z),T x,T y,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,PARENTHESIS_ARGS,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,0);
CREATE_OBJECT_TYPED(Point3D,(x,y,z),T x,T y,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 y,T z) {
 
  DEBUG(cerr << "Universe<T>::createPoint3Dptr" << endl;)

  Point3D<T> * pt3d_ptr = new Point3D<T>(x,y,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(), containerPoint3DptrlistC.end(),
         // 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,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>,T,T,T>(p.x+s,p.y+s,p.z); // bottom ,right x,left y
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p2,p3);
  Point3D<T> & p4 = createPoint3DReflistC<Point3D<T>,T,T,T>(p.x,p.y+s,p.z); // bottom ,left y
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p3,p4);
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p,p4);

  Point3D<T> & ptop = createPoint3DReflistC<Point3D<T>,T,T,T>(p.x,p.y,p.z+s);
  Point3D<T> & p2top = createPoint3DReflistC<Point3D<T>,T,T,T>(p.x+s,p.y,ptop.z); // top ,right x
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p,p2top);
  Point3D<T> & p3top = createPoint3DReflistC<Point3D<T>,T,T,T>(p.x+s,p.y+s,ptop.z); // top ,right x,left y
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p2top,p3top);
  Point3D<T> & p4top = createPoint3DReflistC<Point3D<T>,T,T,T>(p.x,p.y+s,ptop.z); // top ,left y
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p3top,p4top);
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(ptop,p4top);

  // vertical edges
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p,ptop);
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p2,p2top);
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p3,p3top);
  createEdge3DReflistC<Edge3D<T>,Point3D<T> &,Point3D<T> &>(p4,p4top);
  
}


// DEPRECATED
//template Point3D<float> & Universe<float>::createObjectRef(float,float,float) ; // works too
template Point3D<float> & Universe<float>::createObjectRef<Point3D<float>,float,float,float>(float,float,float) ;
//template int Universe<float>::createObjectRef<int,float,float,float>(float,float,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>,float,float,float>(1,0,0);
template Point3D<float> & Universe<float>::createPoint3DReflistC<Point3D<float>,float,float,float>(float,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,float,float>(float,float,float) ;

template Vector3D<float> & Universe<float>::createVector3DRefvectorC<Vector3D<float>,float,float,float>(float,float,float) ;


template std::ostream&  operator<<  (std::ostream &, const Universe<float> &); // does not work

(base) albedo-2:vision3D mattei$ make COMPILING Universe.cpp g++ -c -o Universe.o Universe.cpp -Wall -std=c++17 -I. -DDEBUG_BUILD -DDISPLAY_CONSTRUCTOR -DCHECK_MEMORY Universe.cpp:468:25: error: explicit instantiation of undefined function template 'operator<<' template std::ostream& operator<< (std::ostream &, const Universe &); // does not work ^ ./Universe.hpp:109:39: note: explicit instantiation refers here template std::ostream& operator<< (ostream &, const Universe &); // does not work !!! ^ 1 error generated. make: *** [Universe.o] Error 1

Aucun commentaire:

Enregistrer un commentaire